RandomAccessFile 的默认实现是“损坏的”,因为您无法指定文件的编码方式。
我正在寻找符合以下条件的替代方案:
- 编码感知
- 随机访问!(处理非常大的文件,需要能够使用字节偏移量定位光标而不流式传输整个内容)。
我在 Commons IO 中闲逛了一下,但那里什么都没有。我宁愿不必自己实现这一点,因为有太多地方可能出错。
RandomAccessFile 的默认实现是“损坏的”,因为您无法指定文件的编码方式。
我正在寻找符合以下条件的替代方案:
我在 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;
}