可识别编码的RandomAccessReader实现?

时间:2013-04-25 07:15:32

标签: java character-encoding

RandomAccessFile的默认实现是“已损坏”,因为您无法指定文件所在的编码。

我正在寻找符合以下标准的替代方案:

  1. 编码感知
  2. 随机访问! (处理非常大的文件,需要能够使用字节偏移定位光标而不流式传输整个文件)。
  3. 我在Commons IO中蠢蠢欲动,但那里什么都没有。我宁愿不必自己实现这个,因为有太多的地方可能会出错。

2 个答案:

答案 0 :(得分:1)

RandomAccessFile用于访问二进制数据。无法有效地创建适合所有情况的随机访问编码文件。

即使您找到了这样的解决方案,我也会仔细检查以确保它符合您的需求。

如果你要写它,我会建议考虑行和列的随机位置而不是文件开头的字符偏移量。

这样做的好处是你只需要记住每一行的起点,你可以扫描一行来获得你的角色。如果索引每个字符的位置,则每个字符可以使用4个字节(假设文件大于4 GB)

答案 1 :(得分: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;
}