使用 Java 在 Windows 中删除文件失败
Posted
技术标签:
【中文标题】使用 Java 在 Windows 中删除文件失败【英文标题】:Failed to delete a file in Windows using Java 【发布时间】:2017-04-04 00:49:06 【问题描述】:我一直在尝试使用 Java IO file.delete()
API 在 Windows 操作系统中删除文件。但是它失败并返回false。相同的代码在 Ubuntu 中就像一个魅力。
我已验证该文件的权限允许程序将其删除。此外,该文件的所有输入和输出流都已作为资源尝试打开。
try (InputStream in = new FileInputStream(localFile); OutputStream out = new FileOutputStream(destinationFileName))
使用我测试过的调试器发现,在我删除文件的代码行中,它返回 true
用于后续 API 调用。
file.exists()
file.canRead();
file.canWrite();
file.canExecute();
我什至尝试在调用 delete 之前添加 System.gc()
以确保所有流都已关闭。
不确定这是否是有用的信息,但我什至尝试使用 Apache commons FileUtils.forceDelete(file)
方法,但也失败了。
那么我在这里错过了什么?
更新:
通过使用Files.delete(Paths.get(file.getAbsolutePath()))
,我得到了以下错误。
java.nio.file.FileSystemException: C:\Users\thuvvareka\Desktop\temp\in\sd.xml: The process cannot access the file because it is being used by another process.
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
at java.nio.file.Files.delete(Files.java:1126)
at org.adroitlogic.x.transport.file.FileMessageInjector.finalizeProcessing(FileMessageInjector.java:161)
at org.adroitlogic.x.transport.file.FileMessageInjector.afterProcess(FileMessageInjector.java:123)
at org.adroitlogic.x.transport.file.FileMessageInjector.afterProcess(FileMessageInjector.java:37)
at org.adroitlogic.x.base.trp.ScheduledMessageInjector.lambda$2(ScheduledMessageInjector.java:72)
at org.adroitlogic.x.api.trp.MessageReceiver.lambda$receive$3(MessageReceiver.java:100)
at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760)
at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962)
at org.adroitlogic.x.core.MessageContext.lambda$createNewResponseFuture$2(MessageContext.java:459)
at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760)
at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962)
at org.adroitlogic.x.core.MessageContext.completeMessageFlowSuccessfully(MessageContext.java:332)
at org.adroitlogic.x.base.connector.EgressConnectorElement.sendMessage(EgressConnectorElement.java:185)
at org.adroitlogic.x.base.connector.EgressConnectorElement.process(EgressConnectorElement.java:146)
at org.adroitlogic.x.base.processor.AbstractProcessingElement.processMessage(AbstractProcessingElement.java:103)
at org.adroitlogic.x.base.processor.TraceableProcessingElement.processMessage(TraceableProcessingElement.java:53)
at org.adroitlogic.x.base.connector.IngressConnectorElement.receiveMessage(IngressConnectorElement.java:119)
at org.adroitlogic.x.core.IntegrationPlatform.lambda$receive$0(IntegrationPlatform.java:81)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
【问题讨论】:
File.delete() 是相当老的 API。你可以尝试使用Files.delete(somePath)
,所以也许你会得到更好的错误/异常:见***.com/questions/12139482/…
我已经更新了这个问题,但我得到了例外。
在 Windows 上,您无法删除任何人(包括您自己的进程)打开了文件句柄的文件。这与 Unix 不同,在 Unix 中您可以随时删除它(甚至在之后使用打开的文件描述符)。你可以做什么(如果它是一个应该被删除的临时文件)你可以使用 deleteOnExit,只要你的进程是唯一一个打开文件描述符的进程,这可能会起作用。
@eckes 但是我尝试使用以下简单代码 sn-p 并且它已成功删除该文件。 File file = new File("C:\\Users\\thuvvareka\\Desktop\\temp\\in\\sd.xml"); try (FileInputStream fis = new FileInputStream(file)) System.out.println(fis.getChannel().size()); catch (IOException e) e.printStackTrace(); System.out.println(file.delete());
输出: '0 true'
是的,在您的示例中,文件在被删除之前已关闭。
【参考方案1】:
欢迎使用 Windows。
java.nio.file.FileSystemException: C:\Users\thuvvareka\Desktop\temp\in\sd.xml:
The process cannot access the file because it is being used by another process.
通常,当一个进程在 Windows 中打开一个文件时,操作系统会以一种无法删除该文件的方式锁定该文件。如果是您的程序在您尝试删除文件时打开了该文件,请先关闭该文件,然后再将其删除。如果是另一个程序打开了文件,那么你需要弄清楚是谁打开了它并从那里开始。
当一个进程在 Linux 中打开一个文件时,通常没有什么可以阻止您删除它,这就是您看到不同行为的原因。
【讨论】:
【参考方案2】:我最近遇到了这个问题。我创建了一个解决方法,如果 file.delete()
返回 false,我检查 file.exists()
是否返回 true,如果是,我稍等片刻,然后重试并在尝试多次后放弃。
我未经证实的怀疑是,Windows 上的病毒检查程序会锁定文件以检查文件并等待允许病毒检查程序完成。
// Remove the original file.
if(!file.delete())
// wait a bit then retry on Windows
if (file.exists())
for (int i = 0; i < 6; i++)
Thread.sleep(500);
System.gc();
if (file.delete())
break;
【讨论】:
【参考方案3】:使用Files.delete(filePath)
而不是file.delete()
因为file.delete()
在Windows 上存在一些权限问题。
【讨论】:
本案例的两个 API 没有区别。 它表示您的文件已在 JVM 中打开。请尝试关闭文件并重试,因为无法删除 JVM 打开的文件。希望它会有所帮助。 @SakibSami 关闭文件是什么意思。 Java try with resources 验证所有资源(文件流)都将使用 try 子句关闭。【参考方案4】:我有同样的问题。
做out.close();
解决吧。
只要您没有关闭它,System.gc() 就不会删除到 OutputStream 的链接。
【讨论】:
【参考方案5】:也许您可以使用 System.Runtime.exec() 运行终端/命令行命令来删除特定文件。这可能在某种程度上取决于平台,但要输入到 exec() 函数的命令可能因操作系统属性而异。
可以通过查看这个线程来判断当前运行的java程序的操作系统。
How do I programmatically determine operating system in Java?
在 linux 中,您的行将如下所示:
System.Runtime.exec("rm <path to file>");
【讨论】:
以上是关于使用 Java 在 Windows 中删除文件失败的主要内容,如果未能解决你的问题,请参考以下文章
错误:任务“:app:processDebugResources”执行失败。 > java.io.IOException: 无法在 android studio 中删除文件夹“”