我建立了一个简单的测试,它可以无限循环地创建和删除文件(名称不变)。该测试确实运行了几秒钟(有时超过77,000次迭代!),然后由于以下异常而失败:
Exception in thread "main" java.io.IOException: Access is denied at java.io.WinNTFileSystem.createFileExclusively(Native Method) at java.io.File.createNewFile(Unknown Source) at DeleteTest.main(DeleteTest.java:11)
这是测试逻辑:
final File f = new File(pathname); while (true) { final boolean create = f.createNewFile(); if (!create) { System.out.println("crate failed"); } else { final boolean delete = f.delete(); if (!delete) { System.out.println("delete failed"); } } }
这怎么可能?删除呼叫不会失败。它会说明一切。因此删除总是成功但createNewFile失败。这就是MSDN关于Win32 API函数的说法DeleteFile:
createNewFile
DeleteFile
DeleteFile函数在关闭时将文件标记为要删除。因此,在关闭文件的最后一个句柄之前,不会发生文件删除。随后调用CreateFile打开文件失败,并显示ERROR_ACCESS_DENIED。
所以createNewFile不关闭文件?openjdk源告诉我们文件 已 关闭:
JNIEXPORT jboolean JNICALL Java_java_io_Win32FileSystem_createFileExclusively(JNIEnv *env, jclass cls, jstring pathname) { jboolean rv = JNI_FALSE; DWORD a; WITH_PLATFORM_STRING(env, pathname, path) { int orv; int error; JVM_NativePath((char *)path); orv = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666); if (orv < 0) { if (orv != JVM_EEXIST) { error = GetLastError(); // If a directory by the named path already exists, // return false (behavior of solaris and linux) instead of // throwing an exception a = GetFileAttributes(path); if ((a == INVALID_FILE_ATTRIBUTES) || !(a & FILE_ATTRIBUTE_DIRECTORY)) { SetLastError(error); JNU_ThrowIOExceptionWithLastError(env, path); } } } else { JVM_Close(orv); rv = JNI_TRUE; } } END_PLATFORM_STRING(env, path); return rv; }
谁能解释这种行为?
我在写问题时找到了解释。我仍然发布问题,因为我想分享我学到的东西。
我的应用程序不是系统访问文件的唯一过程。例如,Windows搜索索引服务可能会打开此文件,因为它想将其添加到索引中。或Windows资源管理器(如果要更新视图)。