跳到一条线并阅读它

时间:2010-11-04 10:04:56

标签: java file io

我必须使用大文件(许多GB),并且需要快速查找以根据请求检索特定行。

我们的想法是保持映射:

some_key -> byte_location

其中字节位置表示行开始的文件中的位置。

编辑:问题有所改变:

首先我用过:

FileInputStream stream = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
FileChannel channel = stream.getChannel();

我注意到FileChannel.position()不会返回读者当前正在阅读的确切位置,因为它是一个“缓冲”阅读器。它读取给定大小的块(这里是16k),所以我从FileChannel获得的是16k的倍数,而不是读者实际读取的确切位置。

PS:文件是UTF-8

2 个答案:

答案 0 :(得分:3)

任何不创建FileInputStream的原因,请致电stream.skip(pos),然后围绕该InputStreamReader创建BufferedReader,并InputStreamReader周围{{1}}?

答案 1 :(得分:2)

我会尝试这样的事情:

    RandomAccessFile raf = new RandomAccessFile(file);
    ...
    raf.seek(position);
    raf.readLine();
    ...

问题是readLine()将每个字节转换为前8位为零的字符。如果你的文件是ASCII或Latin-1,那就没问题了,但UTF-8有问题。

但是,如果您准备使用RandomAccessFile来编写文件,则可以使用readUTF()writeUTF()来读取和编写编码为修改后的UTF-8字符串的“行”。

<强>后续

  

该死... utf-8字符被搞砸

是的......见上文。

使用RandomAccessFile来处理UTF-8的另一个想法:

  1. 寻求理想的位置,
  2. 使用readFully(byte[])方法将一堆字节读入byte[]
  3. 找到pos ==缓冲区中行尾的位置,
  4. 如果找不到,请读取更多字节,连接并转到步骤2.
  5. 如果找到,请使用new String(bytes, 0, pos, UTF-8)转换为Java String。
  6. 这比使用readLine()更麻烦,但是当以随机顺序从文件中读取多行时,它应该比使用FileInputStreamskip()更快。