Java随机文件访问:获取行开始的字节偏移量

时间:2013-09-20 06:46:01

标签: java file-io bufferedreader randomaccessfile

我需要随机访问文本(ASCII)文件中的特定记录,然后从那里读取,直到找到特定的“停止序列”(记录分隔符)。该文件包含多行记录,每个记录由分隔符分隔。每条记录也需要不同的行数!这是特定专业领域中众所周知的文件格式,无法更改。

我想索引文件,以便我可以快速跳转到请求的记录。

在像

这样的类似问题中

How to Access string in file by position in Java

及其中的链接,answer总是引用seek()等各种类的RandomAccessFile方法。我知道这件事!

我遇到的问题是如何获得寻求所需的偏移量! (索引文件)

BufferedReader没有getFilePointer()方法或任何其他方法来从文件的开头获取当前字节偏移量。 RandomAccessFile有一个readLine()方法,但它的表现非常糟糕。根据我的情况,它根本不可用。

我需要逐行读取文件,每次找到记录分隔符时我都需要获取字节偏移量。我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:2)

您可以尝试将BufferedReader类子类化以记住读取位置。但是你不会有搜索功能。

正如您所提到的,记录可以是多行的,但所有记录都由停止序列分隔。鉴于此,您可以像这样使用RandomAccessFile

  1. 有一个字节缓冲区byte b[],比方说大小为8k(这是出于性能原因)

  2. 从此缓冲区中的文件读取8k并尝试查找分隔符(如果未找到),读取另一个8k的块,但先前将数据附加到某个StringBuilder或其他结构。

  3. 当您找到分隔符时,分隔符的位置由自上次分隔符找到后处理的字节数给出(您需要进行一些简单的数学运算)。

  4. 如果记录分隔符超过1个字符,那么棘手的部分就是如此,但这应该是个大问题。

答案 1 :(得分:2)

经过大量的谷歌搜索,试验和错误以及更多我想出了一个简单地包装RandomAccessFile并公开所有方法的解决方案。然而,通过对readLine()中的BufferedReader进行微调,可以大大改善OptimizedRandomAccessFile方法。现在表现与之相同。

这个所谓的类OptimizedRandomAccessFile raf = new OptimizedRandomAccessFile(filePath, "r"); String line = raf.readLine(); int nextByte = raf.read(); 缓冲readLine()调用,只要不调用其他需要或影响文件位置的方法。例如:

nextByte

{{1}}将包含文件中下一行的第一个字节。

完整代码可在bitbucket上找到。

答案 2 :(得分:1)

我会使用以下java.io装饰器序列:

   InputStreamReader    <-- reader, the top reader
   CountingInputStream  <-- cis, stores the position (from Google Guava)
   BufferedInputStream  <-- speeds up file reading
   FileInputStream

然后,您通过实现readLine()方法读取此顶级阅读器,该方法逐个读取字符直到行分隔符。我不会使用BufferedReader,因为它会通过读取一个完整的固定大小的缓冲区来破坏当前位置。

因此,如果我遇到问题,算法就像

一样简单
  1. long lineStartPosition = cis.getCount();
  2. String s = readLine(reader);
  3. if(s.equals(DELIMITER)) { storeToIndex(lineStartPosition, recordData); }

答案 3 :(得分:0)

您可以读取所有数据文件并记录找到分隔符的位置,并将此元数据保存在其他文件中。现在,您可以使用元数据浏览文件(从一个分隔符跳转到另一个分隔符)。每次修改数据文件时,您都必须重新扫描它并重新生成元数据。