Java file.delete() 返回 false,即使 file.exists()、file.canRead()、file.canWrite()、file.canExecute() 都返回 true

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/991489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:56:45  来源:igfitidea点击:

file.delete() returns false even though file.exists(), file.canRead(), file.canWrite(), file.canExecute() all return true

javafilefileoutputstream

提问by Jenny Smith

I'm trying to delete a file, after writing something in it, with FileOutputStream. This is the code I use for writing:

我正在尝试删除一个文件,在其中写入一些内容后,使用FileOutputStream. 这是我用于编写的代码:

private void writeContent(File file, String fileContent) {
    FileOutputStream to;
    try {
        to = new FileOutputStream(file);
        to.write(fileContent.getBytes());
        to.flush();
        to.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

As it is seen, I flush and close the stream, but when I try to delete, file.delete()returns false.

正如所见,我刷新并关闭流,但是当我尝试删除时,file.delete()返回 false。

I checked before deletion to see if the file exists, and: file.exists(), file.canRead(), file.canWrite(), file.canExecute()all return true. Just after calling these methods I try file.delete()and returns false.

我删除前检查,看看是否该文件存在,并且:file.exists()file.canRead()file.canWrite()file.canExecute()一切回归真实。在调用这些方法之后,我尝试file.delete()返回 false。

Is there anything I've done wrong?

我做错了什么吗?

采纳答案by Jenny Smith

It was pretty odd the trick that worked. The thing is when I have previously read the content of the file, I used BufferedReader. After reading, I closed the buffer.

有效的技巧很奇怪。问题是当我之前阅读过文件的内容时,我使用了BufferedReader. 读完后,我关闭了缓冲区。

Meanwhile I switched and now I'm reading the content using FileInputStream. Also after finishing reading I close the stream. And now it's working.

同时我切换了,现在我正在使用FileInputStream. 同样在完成阅读后,我关闭了流。现在它正在工作。

The problem is I don't have the explanation for this.

问题是我对此没有解释。

I don't know BufferedReaderand FileOutputStreamto be incompatible.

我不知道BufferedReaderFileOutputStream不兼容。

回答by neesh

There is no reason you should not be able to delete this file. I would look to see who has a hold on this file. In unix/linux, you can use the lsof utility to check which process has a lock on the file. In windows, you can use process explorer.

您没有理由不能删除此文件。我想看看谁持有这个文件。在 unix/linux 中,您可以使用 lsof 实用程序来检查哪个进程锁定了文件。在 Windows 中,您可以使用进程资源管理器。

for lsof, it's as simple as saying:

对于 lsof,它就像说一样简单:

lsof /path/and/name/of/the/file

for process explorer you can use the find menu and enter the file name to show you the handle which will point you to the process locking the file.

对于进程资源管理器,您可以使用查找菜单并输入文件名以显示句柄,该句柄将指向锁定文件的进程。

here is some code that does what I think you need to do:

这是一些代码,可以完成我认为您需要做的事情:

FileOutputStream to;

try {
    String file = "/tmp/will_delete.txt";
    to = new FileOutputStream(file );
    to.write(new String("blah blah").getBytes());
    to.flush();
    to.close();
    File f = new File(file);
    System.out.print(f.delete());
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

It works fine on OS X. I haven't tested it on windows but I suspect it should work on Windows too. I will also admit seeing some unexpected behavior on Windows w.r.t. file handling.

它在 OS X 上运行良好。我没有在 Windows 上测试过它,但我怀疑它也应该在 Windows 上运行。我也承认在 Windows wrt 文件处理上看到了一些意外的行为。

回答by Ravi Wallau

As Jon Skeet commented, you should close your file in the finally {...} block, to ensure that it's always closed. And, instead of swallowing the exceptions with the e.printStackTrace, simply don't catch and add the exception to the method signature. If you can't for any reason, at least do this:

正如 Jon Skeet 评论的那样,您应该在 finally {...} 块中关闭您的文件,以确保它始终关闭。而且,与其用 e.printStackTrace 吞下异常,不如简单地不捕获异常并将其添加到方法签名中。如果你不能因为任何原因,至少这样做:

catch(IOException ex) {
    throw new RuntimeException("Error processing file XYZ", ex);
}

Now, question number #2:

现在,问题编号 2:

What if you do this:

如果你这样做怎么办:

...
to.close();
System.out.println("Please delete the file and press <enter> afterwards!");
System.in.read();
...

Would you be able to delete the file?

你能删除文件吗?

Also, files are flushed when they're closed. I use IOUtils.closeQuietly(...), so I use the flush method to ensure that the contents of the file are there before I try to close it (IOUtils.closeQuietly doesn't throw exceptions). Something like this:

此外,文件在关闭时会被刷新。我使用 IOUtils.closeQuietly(...),所以我使用flush 方法来确保在我尝试关闭文件之前文件的内容在那里(IOUtils.closeQuietly 不会抛出异常)。像这样的东西:

...
try {
    ...
    to.flush();
} catch(IOException ex) {
    throw new CannotProcessFileException("whatever", ex);
} finally {
    IOUtils.closeQuietly(to);
}

So I know that the contents of the file are in there. As it usually matters to me that the contents of the file are written and not if the file could be closed or not, it really doesn't matter if the file was closed or not. In your case, as it matters, I would recommend closing the file yourself and treating any exceptions according.

所以我知道文件的内容在那里。因为对我来说通常重要的是文件的内容被写入而不是文件是否可以关闭,所以文件是否关闭并不重要。在您的情况下,我建议您自己关闭文件并根据情况处理任何异常。

回答by poh

Hopefully this will help. I came across similar problem where i couldn't delete my file after my java code made a copy of the content to the other folder. After extensive googling, i explicitly declared every single file operation related variables and called the close() method of each file operation object, and set them to NULL. Then, there is a function called System.gc(), which will clear up the file i/o mapping (i'm not sure, i just tell what is given on the web sites).

希望这会有所帮助。我遇到了类似的问题,在我的 java 代码将内容复制到另一个文件夹后,我无法删除我的文件。经过大量的谷歌搜索,我明确声明了每个文件操作相关的变量,并调用了每个文件操作对象的 close() 方法,并将它们设置为 NULL。然后,有一个名为 System.gc() 的函数,它将清除文件 i/o 映射(我不确定,我只是告诉网站上给出的内容)。

Here is my example code:

这是我的示例代码:

public void start() {
    File f = new File(this.archivePath + "\" + this.currentFile.getName());
    this.Copy(this.currentFile, f);

    if(!this.currentFile.canWrite()){
        System.out.println("Write protected file " +
           this.currentFile.getAbsolutePath());

        return;
    }


    boolean ok = this.currentFile.delete();
    if(ok == false){
        System.out.println("Failed to remove " + this.currentFile.getAbsolutePath());
        return;
    }
}

private void Copy(File source, File dest) throws IOException {
    FileInputStream fin;
    FileOutputStream fout;
    FileChannel cin = null, cout = null;
    try {
        fin = new FileInputStream(source);
        cin = fin.getChannel();
        fout = new FileOutputStream(dest);
        cout = fout.getChannel();

        long size = cin.size();
        MappedByteBuffer buf = cin.map(FileChannel.MapMode.READ_ONLY, 0, size);

        cout.write(buf);
        buf.clear();
        buf = null;

        cin.close();
        cin = null;

        fin.close();
        fin = null;

        cout.close();
        cout = null;

        fout.close();
        fout = null;

        System.gc();

    } catch (Exception e){
        this.message = e.getMessage();
        e.printStackTrace();
    }
}

回答by Da Martin

Another bug in Java. I seldom find them, only my second in my 10 year career. This is my solution, as others have mentioned. I have nether used System.gc(). But here, in my case, it is absolutely crucial. Weird? YES!

Java 中的另一个错误。我很少找到它们,这是我 10 年职业生涯中的第二个。正如其他人所提到的,这是我的解决方案。我有下界用过System.gc()。但在这里,就我而言,这绝对是至关重要的。奇怪的?是的!

finally
{
    try
    {
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
        System.gc();
    }
    catch (IOException e)
    {
        logger.error(e.getMessage());
        e.printStackTrace();
    }
}

回答by rogerdpack

There was a problem once in ruby where files in windows needed an "fsync" to actually be able to turn around and re-read the file after writing it and closing it. Maybe this is a similar manifestation (and if so, I think a windows bug, really).

在 ruby​​ 中曾经出现过一个问题,Windows 中的文件需要一个“fsync”才能在写入和关闭文件后真正能够转身并重新读取文件。也许这是一个类似的表现(如果是这样,我认为是 Windows 错误,真的)。

回答by Kislay Sinha

I tried this simple thing and it seems to be working.

我尝试了这个简单的事情,它似乎奏效了。

file.setWritable(true);
file.delete();

It works for me.

这个对我有用。

If this does not work try to run your Java application with sudo if on linux and as administrator when on windows. Just to make sure Java has rights to change the file properties.

如果这不起作用,请尝试在 linux 上使用 sudo 运行您的 Java 应用程序,在 Windows 上以管理员身份运行。只是为了确保 Java 有权更改文件属性。

回答by etech

None of the solutions listed here worked in my situation. My solution was to use a while loop, attempting to delete the file, with a 5 second (configurable) limit for safety.

这里列出的解决方案都不适用于我的情况。我的解决方案是使用 while 循环,尝试删除文件,为了安全起见,有 5 秒(可配置)限制。

File f = new File("/path/to/file");

int limit = 20; //Only try for 5 seconds, for safety
while(!f.delete() && limit > 0){
    synchronized(this){
        try {
            this.wait(250); //Wait for 250 milliseconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    limit--;
}

Using the above loop worked without having to do any manual garbage collecting or setting the stream to null, etc.

使用上述循环无需进行任何手动垃圾收集或将流设置为 null 等。

回答by Gangnus

If you are working in Eclipse IDE, that could mean that you haven't close the file in the previous launch of the application. When I had the same error message at trying to delete a file, that was the reason. It seems, Eclipse IDE doesn't close all files after termination of an application.

如果您在 Eclipse IDE 中工作,这可能意味着您没有在应用程序的上一次启动中关闭该文件。当我尝试删除文件时收到相同的错误消息时,这就是原因。看来,Eclipse IDE 在应用程序终止后不会关闭所有文件。

回答by Winnifred

The problem could be that the file is still seen as opened and locked by a program; or maybe it is a component from your program that it had been opened in, so you have to ensure you use the dispose()method to solve that problem. i.e. JFrame frame; .... frame.dispose();

问题可能是文件仍被视为被程序打开和锁定;或者它可能是您程序中的一个组件,它已在其中打开,因此您必须确保使用该dispose()方法来解决该问题。IEJFrame frame; .... frame.dispose();