java.io 上的 FileNotFound(访问被拒绝)异常
Posted
技术标签:
【中文标题】java.io 上的 FileNotFound(访问被拒绝)异常【英文标题】:FileNotFound (Access is denied) Exception on java.io 【发布时间】:2011-12-25 22:34:27 【问题描述】:为什么我在运行这个程序时会收到这个错误?这发生在随机迭代之后。通常在第 8000 次迭代之后。
public static void main(String[] args)
FileWriter writer = null;
try
for(int i = 0; i < 10000; i++)
File file = new File("C:\\Users\\varun.achar\\Desktop\\TODO.txt");
if(file.exists())
System.out.println("File exists");
writer = new FileWriter(file, true);
writer.write(i);
System.out.println(i);
writer.close();
if(!file.delete())
System.out.println("unable to delete");
//Thread.sleep(10);
//writer = null;
//System.gc();
catch(IOException e)
e.printStackTrace();
finally
if(writer != null)
try
writer.close();
catch(IOException e)
e.printStackTrace();
异常发生后,文件不存在。这意味着它正在删除,但 FIleWriter 尝试在此之前获取锁,即使它不是多线程程序。是不是因为 Windows 没有足够快地删除文件,因此 FileWriter 没有获得锁定?如果是这样,那么 file.delete() 方法会在 windows 实际删除它之前返回?
我该如何解决它,因为我在对我的应用程序进行负载测试时遇到了类似的问题。
编辑 1:堆栈跟踪:
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
at java.io.FileWriter.<init>(FileWriter.java:61)
EDIT 2:在程序中添加了 file.exists() 和 file.delete 条件。和新的堆栈跟踪:
7452
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
at java.io.FileOutputStream.openAppend(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
at java.io.FileWriter.<init>(FileWriter.java:90)
at com.TestClass.main(TestClass.java:25)
编辑 3 线程转储
TestClass [Java Application]
com.TestClass at localhost:57843
Thread [main] (Suspended (exception FileNotFoundException))
FileOutputStream.<init>(File, boolean) line: 192
FileWriter.<init>(File, boolean) line: 90
TestClass.main(String[]) line: 24
C:\Users\varun.achar\Documents\Softwares\Java JDK\JDK 6.26\jdk\jre\bin\javaw.exe (09-Nov-2011 11:57:34 PM)
EDIT 4:程序在具有相同操作系统的不同机器上成功运行。现在我如何确保应用程序在部署它的机器上成功运行?
【问题讨论】:
有什么异常,你还想测试什么?Thread.sleep()
似乎有帮助,但我不能将它放入程序中,否则需要一个半世纪才能完成执行。我可以尝试获取锁直到它成功,但是有更好的方法吗?
我会首先尝试检查delete()
的返回值——它总是true
吗?异常是来自writer.close()
,还是来自writer.write()
,还是在创建writer
时?另外,“获得锁”是什么意思?我在程序中没有看到任何锁。
@VarunAchar 有什么例外?并发布堆栈跟踪。
@Joonas:锁定 FileWriter 以写入文件。
【参考方案1】:
在任何操作系统上,您一次只能拥有一定数量的打开文件/线程。你似乎达到了你的操作系统限制。尝试在循环内将 file 设置为 null。
【讨论】:
file = null; writer = null; System.gc();
解决了这个问题。 System.gc()
至关重要。
嗯... 将文件和写入器变量设置为 null 不会改变任何内容,因为当您退出循环(转到下一个文件)时它们将超出范围。而 System.gc() 只是 JVM 执行垃圾收集的一个建议,它不保证它会做任何事情。所以这不是一个合适的解决方案,抱歉。【参考方案2】:
如果我正确理解了您的堆栈跟踪,则尝试创建新的FileWriter
时会出现异常。不进一步调查是不可能知道原因的。
File.delete()
返回的内容。
在尝试创建新的 FileWriter
之前,请检查 File.exists()
返回的内容。
如果之前的delete()
在单线程程序中返回true
,而exists()
紧随其后也返回true
,那么这确实很奇怪。
编辑: 所以看来删除成功了,之后文件就不存在了。当然,它应该如何工作,所以FileWriter
抛出异常的原因很奇怪。再想一想,尝试检查File.getParentFile().canWrite()
。也就是说,您写入目录的权限是否会以某种方式消失。
编辑 2:
不要在具有相同操作系统的不同机器上遇到错误。现在我如何确保此错误不会出现在将要部署它的应用程序中?
到目前为止,您有 一个 机器工作不正常,而 一个 机器工作正常。也许你可以在更多的机器上试一试。第一台机器可能以某种方式损坏并导致错误。令人惊讶的是,数字计算机及其程序(我的意思是操作系统和 Java,不一定是您的程序)可能只是“有点损坏”,因此它们几乎始终可以完美地工作,但在某些特定硬件上随机失败& 用例 - 通常在重负载下 - 类似于不正确的多线程程序的行为方式。你的问题不一定是你的错:-)
坦率地说,确保在机器 X 上不会出现错误的唯一方法是在机器 X 上运行程序。不寻常的事情,例如创建和删除同一个文件 8000 次快速继承容易出错,即使它“应该”起作用。计算机、操作系统和 API 并不完美。你做的不寻常的事情越多,缺陷就会越多地显现出来,因为不寻常的使用通常没有日常操作那么彻底地测试。
【讨论】:
不。if(!file.getParentFile().canWrite()) System.out.println("parent file error");
不执行。【参考方案3】:
我遇到了同样的问题,一个 java 程序(单线程)打开,删除然后不断地重新打开同一个文件。
在某些 Windows 系统上,我们遇到了与此处报告的问题相同的问题,在 Linux、Solaris 和各种其他 Windows 系统上它工作正常。
使用SysInternals Process Monitor (now MS) 跟踪程序,它首先在操作系统级别清除删除,并清除后续打开失败并显示 PENDING DELETE 状态。
因此,在实际删除文件之前,OS/NTFS/磁盘级别似乎有一些轻微的延迟,这似乎是我们案例中随机失败的原因。
作为一种解决方法,我将 .delete() 调用更改为仅在其顶部写入 new FileWriter(file) ,这似乎可以正常工作。
该问题并非在所有系统上都出现,一种总是会失败的特定型号,无论是在没有固定数量的循环之后,都是带有 WD Smartdrive 的 Windows 7 / Dell Lattitude E6420,而我的 Windows 7 / Dell Precision M4600 (带有固态驱动器)或带有 Linux 的 T3400 我从来没有遇到过这个问题。
干杯 - 马克
【讨论】:
【参考方案4】:这可能是一个长镜头,但是,您可以尝试使用不直接位于桌面上的文件吗?而不是:
"C:\\Users\\varun.achar\\Desktop\\TODO.txt"
试试:
"C:\\Users\\varun.achar\\SomeOtherDirectory\\TODO.txt"
操作系统可能在这里用所有桌面挂钩杀死你......
根据 cmets 进行编辑:
是否有任何计划作业在“坏”机器上运行? 您是否有系统管理员来调试环境而不是调试环境? 这是否适用于 clean Windows 安装? [95% 的几率] 由于根本原因似乎是环境问题,而不是解决 Windows 配置问题,您是否能够继续执行其他任务,并将其留给保存系统之间差异列表的人?【讨论】:
我的应用程序正在写入的实际文件位于其他目录中。该程序只是重新创建错误。 我刚刚在 OS/X 上运行它 => 运行良好。即使有 10 万次迭代。 (java版本“1.6.0_26”)。我仍然会尝试将目录更改为 ELSE 并重试。 你能在不同的操作系统、不同的物理机上试试吗? (你可以使用VirtualBox 或者只是在安装 Java 的地方使用 ssh) 不要在具有相同操作系统的不同机器上出现错误。现在我如何确保此错误不会出现在将要部署它的应用程序中?【参考方案5】:你能有条件地尝试写入文件吗?
使用 file.exists 然后写入它,因此您可以潜在地避免任何其他问题。这个例外很难说。
http://download.oracle.com/javase/6/docs/api/java/io/File.html#exists()
您是否也可以在那时发布一个线程转储,只是为了进一步调试它。
请在再次写入之前刷新写入器。
【讨论】:
没有帮助。if(!file.delete())
之后的行不执行。在创建 FileWriter
之前存在的 if(file.exists())
也不存在
好的,请每次刷新writer,应该可以解决。也在更新答案。
根据文档,close()
关闭流,首先刷新它。所以显式刷新在这里应该没有区别。【参考方案6】:
这些是您在删除文件http://www.java2s.com/Code/Java/File-Input-Output/DeletefileusingJavaIOAPI.htm之前应该处理的场景
至少检查程序中的返回值。
【讨论】:
没有帮助。if(!file.delete())
之后的行不执行。在创建 FileWriter
之前存在的 if(file.exists())
也不存在
尝试一些奇怪的东西。更改文件位置后尝试相同的程序并更改文件名。
每次异常发生后的迭代次数是否也相同?
当您遇到异常时,请尝试在 catch 块中再次创建 FileWriter
。同名也不同。【参考方案7】:
感谢大家帮助我,但这就是最终解决的方法。
public static void main(String[] args)
FileWriter writer = null;
try
for(int i = 0; i < 10000; i++)
File file = new File("C:\\tenant-system-data\\abc.txt");
if(!file.getParentFile().canWrite())
System.out.println("parent file error");
if(file.exists())
System.out.println("File exists");
int count = 0;
while(count++ < 5)
try
file.createNewFile();
break;
catch(IOException e)
try
Thread.sleep(100);
catch(InterruptedException e1)
e1.printStackTrace();
writer = new FileWriter(file, true);
writer.write(i);
System.out.println(i);
writer.close();
if(!file.delete())
System.out.println("unable to delete");
//Thread.sleep(10);
//writer = null;
//System.gc();
catch(IOException e)
e.printStackTrace();
finally
if(writer != null)
try
writer.close();
catch(IOException e)
e.printStackTrace();
【讨论】:
【参考方案8】:我也遇到了同样的问题(FileWriter & Access Denied)。
我的猜测原因是:Windows 7 锁定了文件,因为文件内容的预览显示在资源管理器窗口中(在窗口中选择了文件)。
解决方案:我在资源管理器窗口中取消选择该文件。并且 IOException 消失了。
【讨论】:
这应该是一条评论。【参考方案9】:您在目录中有删除权限,但没有创建权限。
【讨论】:
第 8000 次迭代中出现错误,这意味着它正在删除和创建前 8000 次以上。 @VarunAchar 如果您真的在一个会话中创建 > 8,000 个文件,我会质疑您的设计。您应该使用数据库。 没有真正创建 8000 个文件.. 一个文件被一遍又一遍地创建和删除。我这样做是为了实际填充我的数据库以进行负载测试。该文件用作 DB 故障转移功能,以保持 DB 和 lucene 之间的状态一致。以上是关于java.io 上的 FileNotFound(访问被拒绝)异常的主要内容,如果未能解决你的问题,请参考以下文章
getInputStream() 上的 java.io.FileNotFoundException
Android上的java.io.FileNotFoundException,打开失败:ENOENT(没有这样的文件或目录)
Windows 上的 Hudson - 错误:java.io.IOException:无法运行程序“sh”
WSL 上的齐柏林飞艇。 java.io.IOException:无法启动解释器进程