2

文件系统 AirportHDD 从一开始就被挂载(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 是通过网络安装的硬盘),输出就会一直说:true,true,...当我打开 finder 并转到此目录时,输出更改为:false,false , ...

当文件再次添加(通过另一台电脑)时,输出仍然是:假,假,...

但是如果再次打开 finder 并单击目录,finder 会显示现有文件,输出会突然变为:false, true, true, true, ...

笔记:

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

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

  • 刚刚在测试时发现使用 samba 共享一切都可以,但使用 AFP 就无法正常工作

有没有办法告诉java做和finder一样的事情,比如刷新,或者不要尝试缓存,无论如何?

4

3 回答 3

1

我想您可能正在寻找WatchService。Oracle 也很友好地提供了教程

由于无法保证这些链接的使用寿命,我将在几分钟内编辑示例代码。我只是想让你知道我想我找到了一些东西,以防你想开始自己看。

更新 按照链接的教程,我想出了这样的代码。我不确定它会起作用(没有时间测试它),但它可能足以让你开始。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
于 2013-08-14T14:42:01.597 回答
1

这是一个显示问题的 JUnit 测试在 OSX Mavericks 上使用 Samba 时仍然会出现问题。一个可能的原因由以下声明解释: http ://appleinsider.com/articles/13/06/11/apple-shifts-from-afp-file-sharing-to-smb2-in-os-x-109-小牛队

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

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

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;
        }
    }
}

checkExists 源代码:

/**
 * 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;
}
于 2014-04-21T10:28:12.383 回答
-1

The problem is the network file system AFP. With the use of SAMBA everything works like expected.

Maybe the OS returns the wrong file info in OSX with the use of AFP in these scenarios.

于 2013-09-03T20:13:25.977 回答