读取字符行并获取文件位置

And*_*mas 22 java nio java-io

我正在从文本文件中读取连续的字符行.文件中字符的编码可能不是单字节.

在某些时候,我想获得下一行开始的文件位置,这样我可以稍后重新打开文件并快速返回到该位置.

问题

是否有一种简单的方法可以做到这两点,最好是使用标准的Java库?

如果没有,什么是合理的解决方法?

理想解决方案的属性

理想的解决方案是处理多种字符编码.这包括UTF-8,其中不同的字符可以用不同的字节数表示.理想的解决方案主要依赖于受信任且支持良好的库.最理想的是标准Java库.第二好的是Apache或Google库.解决方案必须是可扩展的.将整个文件读入内存不是一种解决方案.返回位置不应要求在线性时间内读取所有先前字符.

细节

对于第一个要求,BufferedReader.readLine()是有吸引力的.但缓冲显然会干扰获得有意义的文件位置.

不太明显,InputStreamReader也可以提前读取,干扰获取文件位置.从InputStreamReader文档:

为了能够有效地将字节转换为字符,可以从基础流中提取比满足当前读取操作所需的更多字节.

该方法RandomAccessFile.readLine() 每个字符读取一个字节.

通过取字符的低八位的字节值并将字符的高八位设置为零,将每个字节转换为字符.因此,此方法不支持完整的Unicode字符集.

Jef*_*eff 9

如果你BufferedReader从a 构造一个FileReader并保留FileReader代码可访问的实例,你应该能够通过调用获得下一行的位置:

fileReader.getChannel().position();
Run Code Online (Sandbox Code Playgroud)

打电话给bufferedReader.readLine().

BufferedReader可以用大小为1的输入缓冲区,如果你愿意来换取位置精度性能提升构造.

备用解决方案 自己跟踪字节会出现什么问题:

long startingPoint = 0; // or starting position if this file has been previously processed

while (readingLines) {
    String line = bufferedReader.readLine();
    startingPoint += line.getBytes().length;
}
Run Code Online (Sandbox Code Playgroud)

无论基础标记或缓冲如何,这都可以使字节数精确到您已处理的内容.你必须考虑你的计数中的行结尾,因为它们被剥离了.

  • BufferedReader缓冲其输入.对BufferedReader.readLine()`的调用可以从底层FileReader读取更多信息,而不仅仅是下一行 - 将位置留在后续行的位置. (2认同)
  • @Jeff `FileReader` 没有 `getChannel`。除了 `FileInputStream` 不能转换为 `BufferedReader` 并且使用 `FileInputStream.getChannel().position()` 根本不会推进文件指针(意味着你每次调用时都会得到相同的位置值) (2认同)