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

我正在尝试使用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(); } } 

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

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

有什么我做错了吗?

Java中的另一个错误。 我很lessfind他们,只有我10年职业生涯中的第二个。 正如其他人所说,这是我的解决scheme。 我有幽默使用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(); } } 

这个技巧很有效。 事情是当我以前读过文件的内容时,我使用了BufferedReader 。 读完之后,我closures了缓冲区。

同时我切换,现在我正在阅读使用FileInputStream的内容。 读完后,我closures了stream。 现在它正在工作。

问题是我没有这个解释。

我不知道BufferedReaderFileOutputStream是不兼容的。

我试过这个简单的东西,它似乎工作。

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

它适用于我。

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

在尝试删除/重命名任何文件之前,必须确保所有读者或作者(例如: BufferedReader / InputStreamReader / BufferedWriter )都已正确closures。

当您尝试从文件读取/写入数据时,该文件由进程保存,直到程序执行完成才释放。 如果要在程序结束之前执行删除/重命名操作,则必须使用java.io.*类附带的close()方法。

正如Jon Skeet评论的那样,您应该在finally {…}块中closures文件,以确保它始终closures。 而且,不要使用e.printStackTrace来吞食exception,只是不要将exception添加到方法签名中。 如果你不能以任何理由,至less这样做:

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

现在,问题#2:

如果你这样做:

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

你能删除文件吗?

另外,文件在closures时被刷新。 我使用IOUtils.closeQuietly(…),所以我使用flush方法来确保文件的内容在我尝试closures它之前(IOUtils.closeQuietly不会抛出exception)。 像这样的东西:

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

所以我知道文件的内容在那里。 由于文件的内容通常对我来说很重要,而不是文件是否可以closures,所以文件是否closures并不重要。 在你的情况,因为它很重要,我会build议你自己closures文件,并根据处理任何exception。

没有理由你不应该能够删除这个文件。 我会看看谁拥有这个文件。 在unix / linux中,可以使用lsof实用程序来检查哪个进程在文件上有锁。 在Windows中,您可以使用进程pipe理器。

对于LSF来说,就像说:

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

对于进程资源pipe理器,您可以使用查找菜单并input文件名向您显示将指向进程locking文件的句柄。

这里是一些代码,做我认为你需要做的事情:

 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(); } 

它在OS X上工作正常。我没有在Windows上testing过,但我怀疑它也可以在Windows上工作。 我也会承认看到一些意外的行为在Windows Wrt文件处理。

如果您在Eclipse IDE中工作,那可能意味着您在上次启动应用程序时没有closures文件。 当我试图删除一个文件时有同样的错误信息,那就是原因。 看来,Eclipse IDE在应用程序终止后不会closures所有文件。

希望这会有所帮助。 我遇到类似的问题,我的Java代码将内容的副本复制到另一个文件夹后,无法删除我的文件。 广泛的search后,我明确地宣布每个文件操作相关的variables,并调用每个文件操作对象的close()方法,并将它们设置为NULL。 然后,有一个名为System.gc()的函数,它将清除文件I / O映射(我不知道,我只是告诉网站上给出的)。

这是我的示例代码:

 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(); } } 

答案是当你加载文件,你需要应用“closures”的方法,在任何代码行,对我工作

在ruby中有一个问题,那就是在windows中的文件需要一个“fsync”才能在写入和closures文件后真正能够转向并重新读取文件。 也许这是一个类似的performance(如果是这样,我认为是一个Windows错误,真的)。

这里列出的解决scheme没有在我的情况下工作。 我的解决scheme是使用while循环,试图删除文件,5秒(可configuration)的安全限制。

 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--; } 

使用上面的循环工作,而不必做任何手动垃圾收集或设置stream为空等。

问题可能是该文件仍被视为被程序打开和locking; 或者它可能是程序中已经打开的组件,所以你必须确保使用dispose()方法来解决这个问题。 即JFrame frame; .... frame.dispose(); JFrame frame; .... frame.dispose();

您必须closures所有stream或使用try-with-resource块

 static public String head(File file) throws FileNotFoundException, UnsupportedEncodingException, IOException { final String readLine; try (FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); LineNumberReader lnr = new LineNumberReader(isr)) { readLine = lnr.readLine(); } return readLine; } 

如果file.delete()发送false,那么在大多数情况下你的Bufferedreader句柄将不会被closures。 closures,它似乎正常工作。

我在Windows上遇到同样的问题。 我以前用scala逐行读取文件

 Source.fromFile(path).getLines() 

现在我把它看作一个整体

 import org.apache.commons.io.FileUtils._ // encoding is null for platform default val content=readFileToString(new File(path),null.asInstanceOf[String]) 

在阅读和现在正确closures文件

 new File(path).delete 

作品。

对于Eclipse / NetBeans

重新启动你的IDE并再次运行你的代码,经过一个小时的努力,这对我来说只是一个骗术。

这是我的代码:

 File file = new File("file-path"); if(file.exists()){ if(file.delete()){ System.out.println("Delete"); } else{ System.out.println("not delete"); } } 

输出:

删除