【问题标题】:Jumping to a line and reading it跳到一行并阅读它
【发布时间】:2010-11-04 10:04:56
【问题描述】:

我必须处理大文件(许多 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 格式

【问题讨论】:

  • 你的文件编码是什么?
  • 问题是什么?如何跳转到输入流中的给定位置? in.skip(pos);。或者如何找到想要跳转的位置来阅读整行而不是部分?

标签: java file io


【解决方案1】:

有什么理由不创建FileInputStream,调用stream.skip(pos),然后围绕它创建一个InputStreamReader,然后在InputStreamReader 周围创建一个BufferedReader

【讨论】:

  • InputStreamReader 是我正在寻找的缺失链接。谢谢。
  • @arnaud:如果您实际上不知道要阅读的位置,那么很难了解如何解决这个问题...在不阅读所有数据的情况下阅读特定行基本上很难.您的文件会长期保持不变吗?如果是这样,您可以花一些精力准确地阅读整个内容并记住 exact 偏移量。
  • 计划是对所有数据进行第一次扫描,逐行读取并存储一些“检查点”:重要的行及其位置。一旦这个索引在内存中并且请求到来,目标是跳转到最近的检查点并进行快速查找。
  • ……啊……我想唯一的办法就是扩展类并自己存储位置。
【解决方案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. locate pos == 缓冲区中行尾的位置,
  4. 如果未找到,读取更多字节,连接并转到第 2 步。
  5. 如果找到,使用new String(bytes, 0, pos, UTF-8) 转换为Java 字符串。

这比使用readLine() 更麻烦,但在以随机顺序从文件中读取多行时,它应该比使用FileInputStreamskip() 更快。

【讨论】:

  • 该死 ...utf-8 字符被搞砸了
猜你喜欢
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
相关资源
最近更新 更多