Java 如何转换文件';将行号设置为字节偏移量(或使用BufferedReader获取每行开头的字节偏移量)?

Java 如何转换文件';将行号设置为字节偏移量(或使用BufferedReader获取每行开头的字节偏移量)?,java,android,Java,Android,我正在使用一个包装在LineNumberReader中的文件阅读器来索引一个大的文本文件,以便以后快速访问。问题是我似乎找不到直接读取特定行号的方法。BufferedReader支持skip()函数,但我需要将行号转换为字节偏移量(或首先索引字节偏移量) 我使用RandomAccessFile对它进行了尝试,虽然它可以工作,但在最初的索引过程中速度非常慢。BufferedReader的速度非常快,但是。。。好吧,你看到问题了 一些关键信息: 文件可以是任意大小(当前为35000行) 它存储在A

我正在使用一个包装在LineNumberReader中的文件阅读器来索引一个大的文本文件,以便以后快速访问。问题是我似乎找不到直接读取特定行号的方法。BufferedReader支持skip()函数,但我需要将行号转换为字节偏移量(或首先索引字节偏移量)

我使用RandomAccessFile对它进行了尝试,虽然它可以工作,但在最初的索引过程中速度非常慢。BufferedReader的速度非常快,但是。。。好吧,你看到问题了

一些关键信息:

  • 文件可以是任意大小(当前为35000行)
  • 它存储在Android的内部文件系统中(确切地说是通过getFilesDir()
  • 不幸的是,格式设置不是固定宽度(因此需要逐行读取)
有什么想法吗

问题是我似乎找不到直接读取特定行号的方法

除非你知道每行的长度,否则你无法直接阅读

没有快捷方式,您需要先读取整个文件,然后手动计算偏移量


我只需要使用BufferedReader,然后获得每个字符串的长度,并为EOL字符串添加1(或2?)。

考虑将文件索引与大文本文件一起保存。如果此文件是在服务器或设备上生成的,则只需生成一次索引,然后将其与文件一起分发和/或保存即可

我建议使用int[],其中每个值都是第n*(索引+1)行的绝对偏移量(以字节为单位)。所以你可以有一个35000大小的数组,每行开头,或者一个350大小的数组,每100行开头

下面是一个示例,假设您有一个
索引
文件,其中包含int值的原始序列:

public String getLineByNumber(RandomAccessFile index, 
                              RandomAccessFile data, 
                              int lineNum) {
    index.seek(lineNum*4);
    data.seek(index.readInt());
    return data.readLine();
}

结束之前的评论:

您可以使用
RandomAccessFile
首先对字节进行计数,然后手动解析读取的内容以查找行,或者使用
LineNumberReader
首先逐行读取并手动计算每行字符的字节数(utf 16中的2个字节?)

我试着用它 随机访问文件,当它工作时, 这是可怕的缓慢的过程中 初始索引

你已经开始了困难的部分。现在来看更难的部分

BufferedReader的速度非常快, 但是


您使用RandomAccessFile时是否有什么原因使其速度比必须的慢?你一次读了多少字节?如果您一次读取一个字节,它将是慢速的。如果一次读取一个字节数组,可以加快速度,并将字节数组用作缓冲区。

如果行的长度不是固定的,那么在读取时,如果不跟踪,就无法直接从行号到字节位置。当然,除非你在阅读时创建一个索引,跟踪字节位置和行号之间的关系(正如我提到的,这是保持跟踪的)。我完全可以在初始索引期间跟踪字节位置,但是我怎么做呢?如果不使用RandomAccessFile,我找不到一种方法来获取每个readline()之后的当前偏移量。@请使用RandomAccessFile一次对文件进行索引,然后打开一个索引文件,并将每个偏移量写入文件。@wirbly这是您的答案。在写入BufferedOutputStream时,每次看到EOL时,将当前文件位置写入索引文件。Easy<代码>int filePos=0;BufferedReader reader=new BufferedReader(新的InputStreamReader(instream);byte[]buf=reader.readLine().getBytes();indexFile.writeInt(filePos);filePos+=buf.length;outstream.write(buf,0,buf.length)文件编码会对使用string.length()产生影响吗要获取字节计数?如果是,是否有更可靠的方法来获取每个readline()的实际字节数?@wirbly是的,编码绝对会对以字节为单位测量的行长度产生影响。我使用RandomAccessFile的readline()方法读取每行,并使用getFilePointer()跟踪偏移量使用字节数组会比readline()更快吗是的,@wirlby,根据它的文档,一次读取一个字节,直到检测到一个行终止符。MJB的答案与你想要的完全一致:RAF加了一个缓冲区。啊,这就解释了速度。我正在努力实现MJB的方法。我会的,但我无法控制原始文本文件的生成。我在做什么应该做的是事后生成索引。(加上原始文件不是静态的,因此必须在运行时创建索引)link+1;我想我在一年前读了这篇链接文章,但懒得再搜索:)我只是简单地浏览了一下,它看起来可能会做出一些EOL假设,所以人们应该注意这一点。这绝对是我一直在寻找的梦想课程。:)关于EOL问题,你是对的,但我在文件的末尾得到了一个IOException。你能看到一些快速修复方法吗?(我正在使用getNextLine()顺便说一句)对不起,我还没有机会更深入地了解这一点。