簡體   English   中英

Java File.exists和其他文件操作為現有文件(網絡,macosx)返回錯誤結果

[英]Java File.exists and other File operations returning wrong results for an existing File (network, macosx)

從頭開始安裝文件系統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);
    }
}

輸出為:true,true,...

一旦我從另一台計算機上刪除了文件(AirportHDD是通過網絡安裝的硬盤),輸出就會一直說:true,true,...當我打開finder並轉到該目錄時,輸出更改為:false,false ,...

當再次添加文件(通過另一台PC)時,輸出仍然是:false,false,...

但是,如果再次打開查找程序並單擊目錄,查找程序會顯示現有文件,則輸出突然變為:false,true,true,true,...。

注意:

  • 只要java“認為”文件不存在,所有其他文件操作(如打開讀取)都會失敗

  • 如果程序本身正在創建和刪除文件,則不會發生問題

  • 剛剛在測試時發現,使用samba共享所有內容都可以,但是使用AFP則無法使用

有沒有辦法告訴Java做與finder一樣的事情,例如刷新,或者不嘗試緩存,無論如何?

我認為您可能正在尋找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

這是一個顯示問題的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;
}

問題是網絡文件系統AFP。 通過使用SAMBA,一切都可以按預期進行。

在這些情況下,也許OS使用AFP在OSX中返回了錯誤的文件信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM