转到Java中的文件行号

时间:2014-02-05 11:55:34

标签: java string file

我想知道如何在java中直接到达文本文件的特定行号。 一种方法就是这样。

int line=0;
BufferedReader read=new BufferedReader(new FileReader(Filename));
while(read.readLine()!=null){
   line++;
   if(line==LIMIT) break;
}

但这会创建很多String对象,除非gc运行,否则不会释放它们。 请提供一个快速且不会消耗大量内存的解决方案。

PS:我正在阅读一个有数百万行的文件。

3 个答案:

答案 0 :(得分:2)

让我们假设文本文件具有可变长度的行,并且您没有预处理它来创建索引。 (否则,应该可以预先确定第N行的位置,然后"寻找它。)

首先观察到(在上述假设的情况下),如果不在第N行开始之前检查每个字符,就不可能找到第N行。

但你仍然可以通过不会产生大量垃圾的方式来做到这一点。这是一个简单的版本:

BufferedReader br = new BufferedReader(new FileReader(filename));
for (int i = 1; i < LIMIT; i++) {
     while ((ch = br.read()) != '\n') {
         if (ch == -1) {
             // reached the end of file too soon ...
             throw new IOException("The file has < " + LIMIT + " lines");
         }
     }
}
line = br.readLine();

诀窍是跳过线而不将它们形成String个对象。

现在上面有一个小瑕疵。假设文本文件的行由换行符('\n')终止,而readLine可以处理3种行分隔符。但这可以解决......而不会产生额外的垃圾。我会将其作为#34;练习给读者&#34;以及调查调整,例如使用read(char[])代替read()

如果您使用FileInputStream打开文件,获得FileChannel,将字节读入ByteBuffer,然后搜索(byte) '\n',则可能会获得更好的效果。但是代码要复杂得多。


但是,我想强调评论中的观点。你可能浪费你的时间。尽管产生了大量垃圾,但您的原始版本可能会运行得足够快。实际上,当垃圾与非垃圾的比例很高时,GC很快。对于一个读取丢弃线的程序,你几乎可以保证会出现这种情况。

与其花时间了解如何根据错误前提来快速制作程序,您最好编写一个简单版本并测量其在典型输入文件上的性能。只有在程序实际太慢时才进行优化。

答案 1 :(得分:0)

您可以读取块中的数据(可能是1024字节块)和搜索行字符,而不是读取字符串。要读取数据块,可以使用byte数组,因此它将被重用,因此不会出现内存问题。你必须照顾:

  • 处理\r\n字符
  • 文件编码(如Unicode或其他)

以块为单位而不是逐字节读取数据将更有效。

答案 2 :(得分:-2)

我认为这应该有所帮助:

FileReader fr = new FileReader("file1.txt");
BufferedReader br = new BufferedReader(fr);

LineIterator it = IOUtils.lineIterator(br);
 for (int l = 0; it.hasNext(); l++) {
  String line = (String) it.next();
   if (l == LIMIT) {
      return line;
  }
}