我们有几个JUnit测试依赖于创建新文件并阅读它们。但是,无法正确创建文件存在问题。但这个错误来来去去。
这是代码:
@Test
public void test_3() throws Exception {
// Deletes files in tmp test dir
File tempDir = new File(TEST_ROOT, "tmp.dir");
if (tempDir.exists()) {
for (File f : tempDir.listFiles()) {
f.delete();
}
} else {
tempDir.mkdir();
}
File file_1 = new File(tempDir, "file1");
FileWriter out_1 = new FileWriter(file_1);
out_1.append("# File 1");
out_1.close();
File file_2 = new File(tempDir, "file2");
FileWriter out_2 = new FileWriter(file_2);
out_2.append("# File 2");
out_2.close();
File file_3 = new File(tempDir, "fileXXX");
FileWriter out_3 = new FileWriter(file_3);
out_3.append("# File 3");
out_3.close();
....
失败的是第二个文件对象file_2永远不会被创建。有时。然后,当我们尝试写入时,会抛出FileNotFoundException
我们已经尝试了
new File
之后添加睡眠(5秒),没有file_2.exists()
为真,但循环从未停止New File(..)
时捕获SecurityException,IOException甚至throwable,但什么也没找到。有一次,我们创建了所有文件,但file_1是在file_1之前创建的,并且检查创建时间的测试失败了。
我们也尝试添加file_1.createNewFile()
,它总是返回true。
那是怎么回事?我们如何进行依赖于实际文件的测试,并始终确保它们存在?
这已经在java 1.5和1.6中进行了测试,也在Windows 7和Linux中进行了测试。可以观察到的唯一区别是,有时候类似的测试用例会失败,有时会创建file_1而不是
更新
我们尝试了一种新的变体:
File file_2 = new File(tempDir, "file2");
while (!file_2.canRead()) {
Thread.sleep(500);
try {
file_2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
这导致了很多类型的异常:
java.io.IOException: Access is denied
at java.io.WinNTFileSystem.createFileExclusively(Native Method)
at java.io.File.createNewFile(File.java:883)
...但最终确实有效,文件已创建。
答案 0 :(得分:2)
您的程序是否有多个实例同时运行? 检查运行javaw.exe的任何额外实例。如果多个程序同时具有同一文件的句柄,那么事情就会很快变得非常糟糕。
您是否有防病毒软件或其他正在运行的软件可以通过句柄阻止文件创建/删除?
答案 1 :(得分:1)
不要硬编码您的文件名,使用随机名称。这是从可能发生的各种外部情况中抽象出来的唯一方法(多次访问同一文件,权限,文件系统错误,锁定问题等......)。
有一件事是肯定的:使用sleep()或重试可以保证在将来某个时候引起奇怪的错误,避免这样做。
答案 2 :(得分:1)
尝试File#createTempFile,这至少可以保证您没有同名的其他文件仍然可以锁定。
答案 3 :(得分:0)
我做了一些谷歌搜索并基于this lucene bug和this board question似乎表明文件锁定和使用该文件的其他进程可能存在问题。
由于我们在ClearCase上运行它,因此ClearCase在创建文件时执行一些索引或类似操作似乎是合理的。添加循环重复直到文件可读解决了问题,所以我们将继续这样做。虽然非常难看的解决方案。