2013-04-25 34 views
0

的RandomAccessFile的默認實現「破」,因爲你不能指定哪些文件進行編碼是在這個意義上編碼感知的RandomAccessReader實現?

我正在尋找這符合下列條件,替代:

  1. 編碼感知
  2. 隨機訪問! (處理非常大的文件,需要能夠使用字節偏移來定位遊標而不會流式傳輸整個文件)。

我曾在Commons IO中徘徊過,但那裏什麼都沒有。我寧願不必自己實現這一點,因爲它可能出錯的地方太多了。

回答

1

RandomAccessFile用於訪問二進制數據。無法高效地創建適用於所有情況的隨機訪問編碼文件。

即使您找到這樣的解決方案,我會仔細檢查以確保它適合您的需求。

如果你要寫它,我會建議考慮一個隨機的行和列的位置,而不是從文件開始的字符偏移量。

這樣做的好處是,您只需要記住每行的起始位置,並且可以掃描該行以獲取角色。如果每個字符的你指數的位置,這可以使用4個字節爲每個字符(假設該文件是< 4 GB)

+0

我意識到這一點,而且我並不是在尋找適合所有情況的東西。我只需要一個隨機訪問的文件輸入流,以便我可以定位遊標,然後讓InputStreamReader負責編碼。偏移量需要是字節偏移量,而不是字符偏移量。就我而言,該文件可能包含兆字節的二進制數據,其後是字符數據。 – Nim 2013-04-25 07:20:25

+0

你想如何定位光標,從文件的開頭或行/列? – 2013-04-25 07:29:28

+0

如果你只是需要字節偏移量,我會使用RandomAccessFile,提取你想要變成一個字符串的字節,並使用字符串構造函數來轉換它們。 – 2013-04-25 07:30:42

0

答案竟然是比我想象的那麼痛苦:

// This gives me access to buffering and charset magic 
new BufferedReader(new InputStreamReader(Channels.newInputStream(randomAccessFile.getChannel()), encoding)), encoding 
.... 

我然後可以實現讀取逐字符的readLine()方法。使用String.getBytes(encoding)我可以跟蹤文件中的偏移量。在底層RandomAccessFile上調用seek()允許我隨意重新定位遊標。可能存在一些潛在的錯誤,但基本測試似乎工作。

public String readLine() throws IOException { 
    eol = ""; 
    lastLineByteCount = 0; 
    StringBuilder builder = new StringBuilder(); 

    char[] characters = new char[1]; 
    int status = reader.read(characters, 0, 1); 

    if (status == -1) { 
     return null; 
    } 

    char c = characters[0]; 
    while (status != -1) { 
     if (c == '\n') { 
      eol += c; 
      break; 
     } 

     if (c == '\r') { 
      eol += c; 
     } else { 
      builder.append(c); 
     } 

     status = reader.read(characters, 0, 1); 
     c = characters[0]; 
    } 

    String line = builder.toString(); 

    lastLineByteCount = line.getBytes(encoding).length + eol.getBytes(encoding).length; 

    return line; 
}