2011-07-25 76 views
3

文件返回ASCII「NUL」字符的方法我有一個Java程序讀取使用Java RandomAccessFile的一個給定的文件和程序將根據文件內容進行一些處理。該文件是由另一個java進程更新的日誌文件。讀取文件的java進程位於另一臺機器上,並具有NFS安裝設置以訪問遠程服務器中的文件。基本上,讀取文件的過程將根據文件長度和RandomAccessFile的位置來查詢文件中的更改,併爲遇到的每個字節調用處理程序方法。問題是,我有時會得到ASCII從RandomAccessFile的返回「NUL」字讀法的Java InputStream讀入用於在NFS掛載位置

int charInt = read(); 

就是charInt在某些情況下,有些時候它返回有效的字符後返回0。但後來我是流中失蹤的人物是完全無效

閱讀我嘗試使用http://commons.apache.org/io/apidocs/org/apache/commons/io/input/Tailer.html從哪裏獲得通知各行的。但是在這些行中,我有時會注意到ASCII NUL字符。 我也不見了蹤跡通在Java IO implementation of unix/linux "tail -f" - 我的java程序是類似的東西,但後來我開始認爲這個問題是與NFS掛載或一些越野車的Java IO試圖從NFS掛載讀時。我從普通文件(不在NFS安裝中)讀取一些測試,並且有一個連續寫入的進程。所有這些測試都取得了成功。 我也嘗試過java BufferedReader,因爲文件流實際上是一個字符流,即使我可以將它視爲字節流。我仍然得到NUL字符。

不知道這是否會事 - NFS掛載爲只讀(RO)之一。 欣賞這方面的任何幫助。謝謝。

我嘗試以下還有:

FileWriter fileWriter; 
    try { 
     fileWriter = new FileWriter("<OUT_FILE>", true); 
    } catch (IOException e) { 
     throw new RuntimeException("Exception while creating file to write sent messages ", e); 
    } 
    BufferedWriter bufWriter = new BufferedWriter(fileWriter); 

    Runtime r = Runtime.getRuntime(); 
    Process p = r.exec("tail -f <PATH_TO_IN_FILE>"); 
    Scanner s = new Scanner(p.getInputStream()); 
    while (s.hasNextLine()) {  
     String line = s.nextLine(); 
     bufWriter.write(line); 
     bufWriter.write(System.getProperty("line.separator")); 
     bufWriter.flush(); 

    } 
    bufWriter.close();        

,仍然我收到NULL字符。在這裏,我正在寫入我讀到一個文件的行,以便我可以比較IN文件和OUT文件。我在一個時間線上看到跳過(帶有NUL字符)。所有其他線比較好 - 所以從大約13000行,我們看到約100行不匹配。另外還有一個奇怪的地方是我的跑步數量較少,而且我可以在這裏看到NUL字符,基本上是以^ C^@^@^@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ 然後有效的行。還有一件事我在錯過這些行的時候注意到了,文件在寫入過程中得到了非常快速的更新,所以基本上xml消息被寫入文件20110729 13:44:06.070097,然後下一個在20110729 13 :44:06.100007。從第二個xml消息中錯過了行。更多發現:我們正在讀取文件的文件路徑位於共享NAS中。

回答

0

您是否嘗試過這樣的事情:

BufferedReader input = new BufferedReader(new FileReader(args[0])); 
    String currentLine = null; 

    while (true) { 

    if ((currentLine = input.readLine()) != null) { 
     System.out.println(currentLine); 
     continue; 
    } 
    try { 
     Thread.sleep(sleepTime); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
     break; 
    } 
    } 

如果沒有可以從文件currentLine閱讀將是空的......

我懷疑有一個特定的NFS + Java的問題,事實您通過NFS訪問文件對VM來說應該是未知的。

+0

謝謝。是的,我已經嘗試過 - 問題是,在某些情況下,我會在打印出來的行中得到NUL字符,當我期望擁有有效的字符時。另外,有時返回的行會變大,因爲流無法讀取LF或CR字符,而是讀取NUL字符。 – gregoryp

+0

然後它是一個編碼問題,如果你打開文件,你可以說它是否是例如UTF-8編碼,如果真的需要,你可以設置行尾。問題可能來自您的java代碼運行的操作系統與寫入NFS安裝文件的操作系統不同。 –

+0

我沒有控制寫入文件的進程。操作系統是相同的 - 只需檢查。不確定JVM使用哪種編碼方式。我相信它應該存在於某些系統屬性中。當寫入過程與讀取過程在同一臺機器上運行時,我無法再現問題。但是當寫入在遠程服務器上完成時,問題就出現了。另外,在兩種情況下,文件更新/寫入的頻率都是相同的 – gregoryp

6

我意識到這個問題,現在是一年多歲,但我會添加什麼,我知道它,以防他人跨越它這個問題絆倒,因爲我有。

在這個問題中所描述的NULL字符出現因異步寫入文件被讀取。更具體地說,來自遠程文件寫入器的數據包已經不按順序到達,並且NAS緩衝器已經提交了稍後的包並且用NUL字符填充了未接收到的數據的區域。當收到丟失的數據包時,NAS緩衝區提交它,覆蓋這些空字符。

在我們第一次遇到這個問題的應用程序中,我們逐行讀取一個文件,並跟蹤最後一行成功讀取的行號(這樣我們可以隨時停止並在我們停止的地方再次啓動)。我們處理這個問題的臨時解決方案只是在每次讀取時特別檢查「\ 0」,並在遇到時關閉文件,等待1秒鐘並重新打開文件,排隊等待我們離開的地方。通常,當我們再次閱讀該行時,實際的文本已被提交。

雖然關閉並重新打開該文件可能看起來很戲劇性,但恢復時不會出現問題。您不能標記/重置BufferedReader來解決它,因爲一旦字符被讀入讀卡器的緩衝區中,它們就不會從文件中重新讀取,每次嘗試再讀取時都會反覆讀取。

獲取底層FileChannel以及讀取和設置position()也會失敗,因爲您在文件中的位置包含讀入緩衝區的字符,您可能還沒有看到,並且最終會跳過看不見的數據。

我們正在測試一個解決方案,我們已經擴展了InputStreamReader類並覆蓋了read(char [],int,int)方法,使用filechannel在每次讀取之前獲取位置,調用超類的讀取方法,檢查\ 0,如果找到文件通道位置,則重置它,返回0作爲讀取的字符數。

相關問題