关闭使用FileOutputStream创建的文件,以便下一步删除。

7

我目前在我的Java代码中遇到了一些与FileOutputStream相关的问题。

实际上,我正在使用FileOutputStream来创建一个文件,但是一旦文件被创建,就没有办法删除它。据我所了解,这可能是由于FileOutputstream没有关闭造成的。

下面是我的代码总结:

     outFile = new FileOutputStream(dir+"\\"+fileName);
     outFile.write("Test");
     outFile.flush();
     outFile.close();
     outFile = null;
     System.gc();

那么就没有办法手动删除这个文件了。当我的程序启动时,我无法通过简单的del命令在Windows上删除它。我还尝试删除dir文件夹的内容,但是使用以下代码也无法成功:

static public void delDir( String place )

{
    File path = new File( place );
    System.out.println(path.exists());//return true
    if( path.exists() )
        {
        File[] f = path.listFiles();
        for( int j = 0 ; j < f.length ; j++ )
            {
            if( f[ j ].isDirectory() )
                {
                deleteDirectory( path+"\\"+f[ j ] );
                }
            f[ j ].delete();
            }
        }
}

我的问题是: 如何在下次删除时关闭此文件(或者如果无法关闭该文件,如何正确地删除它)?

6个回答

13

这是Java中的一个bug。是的,它很少见,但它确实存在;)你能在outFile.close()之后添加以下内容吗?

outFile = null;
System.gc();

然后尝试删除它。如果这种方法不起作用,可能还有其他的方法。请告诉我。

更新

对于我来说,这个方法可行:

public class FileDeleteExample {
    public static void main(String[] args) throws Exception {
        File f = new File("test.txt");

        FileOutputStream outFile = null;

        try {
            outFile = new FileOutputStream(f);
            outFile.write("Test".getBytes());
        } finally {
            outFile.flush();
            outFile.close();
            outFile = null;
            System.gc();
        }

        f.delete();
    }
}

更新

我已经尝试了Sumit Singh提到的示例,通过删除outFile=null; System.gc;这行代码,我也成功运行了该示例。因此,FileOutputStream应该没有问题。你能否尝试上面的简单示例,并说一下是否能够正常工作?

更新

void closeQuietly(FileOutputStream out) {
    try { out.flush(); out.close(); } catch(Exception e) {} 
}

现在只需要在 finally 块中调用该方法即可!


是的,这个例子对我有效。我不知道我的代码哪里出了问题,可能是因为我没有在 finally 中刷新、关闭等等。当我这样做时,需要在 finally 中加入一些 throw 或 try catch,这真的很奇怪。 - user1619114
是的,在最后你也必须捕获异常。在我的例子中,我只是抛出了“Exception”,所以我不需要处理它们^^但这只是为了举例。我认为你应该处理它们。我添加了一段代码供你使用。 - christian.vogel
是的!它起作用了,天啊,非常感谢你。我整晚都在尝试解决这个问题,多亏了你,我终于找到了解决方案!!非常感谢你!!!! - user1619114
我本意想点赞,却不小心点了踩...请更新你的答案,这样我才能改变我的投票(投票已锁定)。谢谢! - dberm22
嗨@dberm22,抱歉没看到你的评论,我已经更新了我的答案。 - christian.vogel
显示剩余3条评论

2

I had the same problem, the delete() method returned false for my File.

In my case, somewhere in between creating the file, writing to its FileOutputStream and deleting the file, i was using a FileInputStream and forgot to call close() for it.

So, maybe somewhere in your code you attached another stream to this file, and left it open.

Before finding the real source of the problem, i used a simle hack to temporarily fix this:

FileOutputStream fos = new FileOutputStream(myFile);
fos.close();
myFile.delete();

Right before calling delete on my File, i created another FileOutputStream over it and then just called close().

This unlocks all previuous locks on this file and lets you call delete().

Still it is not a good practice to do this. You should find out who uses your file and solve it the right way.


0

不是很相关,但:

这个关于文件关闭的解决方案帮助我解决了另一个问题。当我从Java 6运行程序时,新进程会被挂起,直到我关闭我的应用程序(在Java 7中没问题)。 基于这个答案的解决方案有所帮助:

    String[] com = new String[]{javaRun, arg1, arg2, arg3, arg4};

    Process proc = Runtime.getRuntime().exec(com, null, dir);

    proc = null;
    System.gc();

这适用于Java 6。感谢您的启发。


0

关闭文件输出和输入流的方法是:

name.close()

你的删除代码看起来很好。我的建议是,除非你有充分的理由使用FileOutputStream,否则最好使用FileIO。程序关闭后,你能删除文件吗?


是的,一旦它们被关闭,我可以删除它们,请阅读我上面提供的代码。 - user1619114

0
最好使用Apache Commons IO中的FileUtils.deleteDirectory。它可以克服Java删除漏洞,减少所使用的代码数量,而且最重要的是,它是有效的。
不要调用
delDir(place);

只需调用

FileUtils.deleteDirectory(new File(place));

更新: 在你的delDir方法中,你调用了:

deleteDirectory(new File(path + "\\" + f[j]));

但是结果是

File[] f = path.listFiles();

文件中已经包含了路径,所以您可以直接使用:

deleteDirectory( f[j].getPath() );

你好,正如你所看到的,是的,我使用了 "deleteDirectory( path+"\"+f[ j ] );",或者我误解了你的建议? - user1619114
你需要下载库http://commons.apache.org/io/download_io.cgi并将JAR文件添加到你的类路径中。 - Reimeus
好的,我已经做了,但是问题还是一样,我得到了相同的异常:"java.io.IOException: 无法删除文件"。 - user1619114

0

问题可能在第一行中:

outFile = new FileOutputStream(dir + "\" + fileName);
  1. 不确定是否需要new。
  2. 不认为目录应包含在路径中。据我所知,FileOutputStream的目录被定义为app内部目录。

希望对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接