java - File.createNewFile() 随机失败

标签 java winapi createfile

我构建了一个简单的测试,它在无限循环中创建和删除文件(名称不变)。该测试确实运行了几秒钟(有时超过 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 的说明:

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with 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 资源管理器(如果它正在更新 View )。

关于java - File.createNewFile() 随机失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10516472/

相关文章:

winapi - 关于 Windows GDI 的困惑。新手程序员

c++ - 创建内存文件

c++ - CreateFile() 返回地址为 FFFFFF 的无效指针

java - 如何在我的 Java 应用程序的根目录中创建一个文件夹?

java - 关于Spring JpaRepository方法线程安全

java - 根据条件将 map 内容放入另一个 map

c# - 如何在 C#.NET 和 C Win32 DLL 之间传递句柄?

winapi - 使用Windows SetTimer()函数

java - net.corda.testing.node.internal.ListenProcessDeathException : The process that was expected to listen on localhost:10000 has died with status: 1

java - 读取带有多个标志的纯文本文件java