Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java File.createNewFile()随机失败_Java_Winapi_Createfile - Fatal编程技术网

Java File.createNewFile()随机失败

Java File.createNewFile()随机失败,java,winapi,createfile,Java,Winapi,Createfile,我构建了一个简单的测试,它在无限循环中创建和删除一个文件(名称不变)。测试确实运行了几秒钟(有时超过77000次迭代!),然后失败,出现以下异常: Exception in thread "main" java.io.IOException: Access is denied at java.io.WinNTFileSystem.createFileExclusively(Native Method) at java.io.File.createNewFile(U

我构建了一个简单的测试,它在无限循环中创建和删除一个文件(名称不变)。测试确实运行了几秒钟(有时超过77000次迭代!),然后失败,出现以下异常:

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
失败。这是关于win32 api函数的说明
DeleteFile

DeleteFile函数在关闭时标记要删除的文件。所以,, 直到文件的最后一个句柄被删除,文件才会被删除 关闭后续调用CreateFile以打开文件失败,原因是 错误\u访问被拒绝

所以
createNewFile
不关闭文件?openjdk源代码告诉我们该文件已关闭:

JNIEXPORT jboolean JNICALL
Java_Java_io_Win32FileSystem_CreateFileExclusive(JNIEnv*env,jclass cls,
jstring路径名)
{
jboolean rv=JNI_FALSE;
德沃德a;
带有\u平台\u字符串(环境、路径名、路径){
int orv;
整数误差;
JVM_NativePath((char*)路径);
orv=JVM_Open(路径,JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL,0666);
如果(orv<0){
if(orv!=JVM_EEXIST){
error=GetLastError();
//如果指定路径下的目录已存在,
//返回false(solaris和linux的行为),而不是
//抛出异常
a=GetFileAttributes(路径);
if((a==无效的\u文件\u属性)||
!(文件属性目录(&U)){
SetLastError(错误);
JNU_ThrowIOExceptionWithLastError(环境,路径);
}
}
}否则{
JVM_-Close(orv);
rv=JNI_真;
}
}结束平台字符串(环境,路径);
返回rv;
}

有人能解释这种行为吗?

我在写问题时找到了解释。我仍然发布了这个问题,因为我想分享我学到的东西

我的应用程序不是系统上访问文件的唯一进程。例如,Windows搜索索引服务可以打开此文件,因为它希望将其添加到其索引中。或windows资源管理器(如果正在更新视图)。

请尝试以下操作:

final File f = new File("file");
    while (true) {
        final boolean create = f.createNewFile();
        if (!create) {
            System.out.println("crate failed");
        } else {
            final boolean delete = f.delete();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                System.out.println("...");
            }
            if (!delete) {
                System.out.println("delete failed");
            }
        }
    }

通过这种方式,我们确保在调用createNewFile之前,文件由delete释放。

这个问题提醒了我最近使用file.renameTo()方法遇到的一个问题。这是(曾经?)由于jvm中的这个错误:

一个奇怪的解决方法是调用System.gc()并再次尝试重命名该文件(它可以工作…)


不确定它是否与您的问题有关,但可能值得探索…

好吧,您的代码确实降低了失败的几率,但它不能确保成功。可能仍有一个进程将文件保持打开状态超过10毫秒。请注意,删除文件的命令已发送给操作系统,在操作系统处理此命令后,任何人都不应阻止它。如果您想确定,请在f.createNewFile()中捕获java.io.IOException,然后等待10毫秒,然后再试一次。在你的情况下,我打赌这是你的防病毒软件。这种事情在av中经常发生。旧的Windows内容索引服务在这方面有一个严重的缺陷。如果您快速创建并删除一个目录,它将打开一个目录句柄(可能使用FindFirstFile),但无法关闭它,留下一个您无法处理的僵尸目录。杀死僵尸的唯一方法是重新启动索引服务。@Gangnus,我明确表示这种行为是随机的。所以:不,这不是许可问题。我明白了。我把答案放在这里仅仅是因为我在寻找类似问题的解决方案,而你的是我读过的其中一页,当我找到解决方案时,我在这里放了一个链接,以便将来帮助别人。它不是你问题的答案或答案,也不是作为答案发表的。
final File f = new File("file");
    while (true) {
        final boolean create = f.createNewFile();
        if (!create) {
            System.out.println("crate failed");
        } else {
            final boolean delete = f.delete();
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                System.out.println("...");
            }
            if (!delete) {
                System.out.println("delete failed");
            }
        }
    }