的RandomAccessFile的默認實現「破」,因爲你不能指定哪些文件進行編碼是在這個意義上編碼感知的RandomAccessReader實現?
我正在尋找這符合下列條件,替代:
- 編碼感知
- 隨機訪問! (處理非常大的文件,需要能夠使用字節偏移來定位遊標而不會流式傳輸整個文件)。
我曾在Commons IO中徘徊過,但那裏什麼都沒有。我寧願不必自己實現這一點,因爲它可能出錯的地方太多了。
的RandomAccessFile的默認實現「破」,因爲你不能指定哪些文件進行編碼是在這個意義上編碼感知的RandomAccessReader實現?
我正在尋找這符合下列條件,替代:
我曾在Commons IO中徘徊過,但那裏什麼都沒有。我寧願不必自己實現這一點,因爲它可能出錯的地方太多了。
RandomAccessFile用於訪問二進制數據。無法高效地創建適用於所有情況的隨機訪問編碼文件。
即使您找到這樣的解決方案,我會仔細檢查以確保它適合您的需求。
如果你要寫它,我會建議考慮一個隨機的行和列的位置,而不是從文件開始的字符偏移量。
這樣做的好處是,您只需要記住每行的起始位置,並且可以掃描該行以獲取角色。如果每個字符的你指數的位置,這可以使用4個字節爲每個字符(假設該文件是< 4 GB)
答案竟然是比我想象的那麼痛苦:
// 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;
}
我意識到這一點,而且我並不是在尋找適合所有情況的東西。我只需要一個隨機訪問的文件輸入流,以便我可以定位遊標,然後讓InputStreamReader負責編碼。偏移量需要是字節偏移量,而不是字符偏移量。就我而言,該文件可能包含兆字節的二進制數據,其後是字符數據。 – Nim 2013-04-25 07:20:25
你想如何定位光標,從文件的開頭或行/列? – 2013-04-25 07:29:28
如果你只是需要字節偏移量,我會使用RandomAccessFile,提取你想要變成一個字符串的字節,並使用字符串構造函數來轉換它們。 – 2013-04-25 07:30:42