Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.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.exists和其他文件操作返回错误的现有文件结果(网络、macosx)_Java_Macos_Networking_Filesystems - Fatal编程技术网

Java File.exists和其他文件操作返回错误的现有文件结果(网络、macosx)

Java File.exists和其他文件操作返回错误的现有文件结果(网络、macosx),java,macos,networking,filesystems,Java,Macos,Networking,Filesystems,文件系统airporthd从一开始就被挂载(AFP),当我启动这个小程序时,文件就存在了。 我一整天都在试图弄明白为什么下面的方法不起作用,但找不到任何解决办法: public static void main(String[] arguments) { while(1==1) { File f=new File( "/Volumes/AirportHDD/test/lock.csv"); System.out.pr

文件系统airporthd从一开始就被挂载(AFP),当我启动这个小程序时,文件就存在了。 我一整天都在试图弄明白为什么下面的方法不起作用,但找不到任何解决办法:

public static void main(String[] arguments)
{
    while(1==1)
    {
        File f=new File(
                "/Volumes/AirportHDD/test/lock.csv");
        System.out.println(f.exists());
        AmySystem.sleep(100);
    }
}
输出为: 真的,真的

一旦我从另一台计算机上删除该文件(AirportHDD是通过网络挂载的硬盘),则输出会一直显示: 真的,真的。。。 当我打开finder并转到这个目录时,输出变为:false,false

再次添加文件(通过另一台pc)时,输出仍为: 假,假

但如果您再次打开finder并单击目录,finder显示现有文件,则输出会突然更改为:false、true、true、true、

注:

  • 此外,只要java“认为”文件不存在,所有其他文件操作(如打开以便读取)都会失败

  • 如果程序本身正在创建和删除文件,则问题不会发生

  • 在测试samba时发现,共享一切都没问题,但使用AFP就行不通了


有没有一种方法可以告诉java做与finder相同的事情,比如刷新,或者不要尝试缓存,不管怎样?

我想您可能正在寻找。甲骨文公司也很友好地提供了一个解决方案

因为不能保证这些链接的寿命,我将在几分钟内编辑一个示例代码。我只是想让你知道,我想我找到了一些东西,以防你想自己去看

更新 在链接教程之后,我产生了如下代码。我不确定它是否有效(没有时间测试),但它可能足以让您开始。
WatchService
还有一个
take()
方法,该方法将等待事件,这意味着您可能会根据上次提供的输出假设文件存在(或不存在)。这将真正取决于这个程序将与什么交互

如果这有效,那就好了。如果没有,也许我们可以根据您遇到的任何错误来解决它。或者,如果其他人比我更熟悉这一点,他们可能会提供更好的代码版本(或者更好的选择)

public static void main(String[] arguments) {
    Path path = Paths.get("/Volumes/AirportHDD/test/lock.csv");
    WatchService watcher = FileSystems.getDefault().newWatchService();
    WatchKey key = null;
    try {
        key = path.register(watcher,
                       ENTRY_CREATE,
                       ENTRY_DELETE);
    } catch (IOException x) {
        System.err.println(x);
    }

    while(true) {//I tend to favor this infinite loop, but that's just preference.
        key = watcher.poll();
        if(key != null) {
            for (WatchEvent<?> event: key.pollEvents()) {
                WatchEvent.Kind<?> kind = event.kind();

                if (kind == OVERFLOW || kind == ENTRY_DELETE) {
                    System.out.println(false);
                }
                else if (kind == ENTRY_CREATE) {
                    System.out.println(true);
                }
            }//for(all events)
        }//if(file event occured)
        else {
            File f=new File(path);
            System.out.println(f.exists());
        }//else(no file event occured)

        AmySystem.sleep(100);
    }//while(true)
}//main() method
publicstaticvoidmain(字符串[]参数){
Path Path=Path.get(“/Volumes/airporthd/test/lock.csv”);
WatchService watcher=FileSystems.getDefault().newWatchService();
WatchKey=null;
试一试{
key=路径寄存器(watcher,
创建的入口,
条目(删除);
}捕获(IOX异常){
系统错误println(x);
}
虽然(真的){//我倾向于这个无限循环,但这只是偏好。
key=watcher.poll();
if(key!=null){
for(WatchEvent事件:key.pollEvents()){
WatchEvent.Kind-Kind=event.Kind();
if(种类==溢出| |种类==条目_删除){
System.out.println(假);
}
else if(种类==条目\u创建){
System.out.println(真);
}
}//(所有事件)
}//如果(发生文件事件)
否则{
文件f=新文件(路径);
System.out.println(f.exists());
}//else(未发生文件事件)
睡眠系统(100);
}//while(true)
}//main()方法

问题在于网络文件系统AFP。通过使用SAMBA,一切都像预期的那样工作


在这些情况下,使用AFP时,操作系统可能会在OSX中返回错误的文件信息。

下面是一个JUnit测试,显示了问题所在 在OSX小牛上使用Samba仍然会出现问题。可能的原因 由以下语句解释:

它积极缓存文件和文件夹属性,并使用机会锁定来更好地缓存数据。

请在下面找到一个检查文件,它将实际尝试读取几个字节并强制进行真正的文件访问,以避免缓存错误行为

JUnit测试:

/**
 * test file exists function on Network drive
 * @throws Exception
 */
@Test
public void testFileExistsOnNetworkDrive() throws Exception {
    String testFileName="/Volumes/bitplan/tmp/testFileExists.txt";
    File testFile=new File(testFileName);
    testFile.delete();
    for (int i=0;i<10;i++) {
        Thread.sleep(50);
        System.out.println(""+i+":"+OCRJob.checkExists(testFile));
        switch (i) {
        case 3:
            // FileUtils.writeStringToFile(testFile, "here we go");
            Runtime.getRuntime().exec("/usr/bin/ssh phobos /usr/bin/touch "+testFileName);
            break;
        }
    }
}
/**
 * check if the given file exists
 * @param f
 * @return true if file exists
 */
public static boolean checkExists(File f)  {
    try {
        byte[] buffer = new byte[4];
        InputStream is = new FileInputStream(f);
        if (is.read(buffer) != buffer.length) { 
            // do something 
        }
        is.close();
        return true;
    } catch (java.io.IOException fnfe) {

    }
    return false;
}

我猜当你通过finder打开它时,它会被装入
。可用和安装是不同的。@rocketboy:这与报告的症状不匹配。显然,如果报告文件存在(初始
true
true
true
),则文件系统已装入。文件系统从一开始就装入,更正了启动情况这是什么类型的网络装入?这听起来确实像是一个缓存问题,在NFS上很常见。它的AFP,是的,它表明只有finder可以执行刷新之类的操作,而其他操作系统调用仍然会得到错误的结果。听起来不错,但我喜欢使用静态方法来告诉我文件是否存在。如果我得到了这项手表服务,我需要注册更改,这些更改可能难以在当前设计中实现。我不会假装了解您的设计,但我知道有些解决方案不兼容。我不确定这是否适用于您的系统设计,但我想这将是您的决定。如果结果证明它不起作用,我相信其他人会找到一个不同的解决方案。thx很多时候我都会尝试实现它,我只是在测试samba共享时发现,一切都可以,但对于AFP,对于当前在OS Mavericks上的samba实现,上面的解决方案无法工作