我必须使用大文件(许多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
答案 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的另一个想法:
readFully(byte[])
方法将一堆字节读入byte[]
,pos
==缓冲区中行尾的位置,new String(bytes, 0, pos, UTF-8)
转换为Java String。这比使用readLine()
更麻烦,但是当以随机顺序从文件中读取多行时,它应该比使用FileInputStream
和skip()
更快。