2013-04-24 70 views
4

我想从文本文件中读取特定的行,但是我不想将文件加载到内存中(它可以变得非常大)。Java阅读第n行

我一直在寻找,但我发现每一个例子都需要阅读每一行(这会减慢我的代码,因为有超过100,000行)或将整个东西加载到数组中,并获得正确的元素(文件将有很多行输入)。

什么,我想要做的一个例子:

String line = File.getLine(5); 

“的代码是不实际的代码,它是由以显示我想要什么”的原则

有没有办法做到这个?

----- -----编辑

我刚刚意识到这个文件将被写入过在读线之间(添加到文件的末尾)。

+2

通过100000行文件的每一行读取是一个非常快速的操作,为什么你认为这是一个问题? – Keppil 2013-04-24 19:59:43

+1

[skip](http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html#skip(long))怎么样?但是,你需要一个固定的行长度或每行的行起始位置,或者至少想到行长度和每行唯一的ID(在这种情况下,你可能需要一个[随机访问文件](http:///docs.oracle.com/javase/tutorial/essential/io/rafs.html)如果你超调)。 – Dukeling 2013-04-24 20:04:06

+0

尝试在RandomAccessFile中使用seek(long pos)方法,然后使用readLine()获取数据。 – VKPRO 2013-04-24 20:08:44

回答

12

有没有办法做到这一点?

除非行的每个字节都是固定的字节数,否则不行。

实际上你不必保持记忆中的每一行 - 但是你必须通读整个文件才能到达你想要的行,否则你将不知道从哪里开始阅读。

+0

哦,好吧我猜我必须逐行阅读它,除非如果什么劫下面说的工作。它仍然一行一行地阅读它,但是你需要映射哪一行是什么偏移量,所以你可以将指针移动到你想要的位置。 – NoLiver92 2013-04-25 07:42:38

3

必须逐行读取文件中的行。否则,你如何知道何时到达第5行(如你的例子)?

编辑:

你可能也想看看Random Access Files这可能是有用的,如果你知道每行有多少字节,因为乔恩斯基特说。

+2

准确地,甚至在随机访问文件中,你也不能逐行阅读 - 只需通过字节。重要的是要记住,行(在文件系统上的文件中)由换行符任意表示。一个1KB的文件可能有1024行,或者只有一行 – darkpbj 2013-04-24 20:05:15

+0

@darkpbj RandomAccessFile有一个readLine()方法,所以我认为你的意思是说RandomAccessFile不能按顺序_seek_。 – rob 2013-04-25 05:09:33

0

做到这一点的唯一方法是没有办法随机从一开始访问基于索引的行生成的每一行是(你只需要记录每一行的末尾)的索引,你有读取该行之前的每个字节。

顺便说一句:读取100,000行可能只需要一秒钟的快速机器。

3

要做到这一点是使用一个BufferedReader(http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedReader.html),因为你可以指定你的缓冲区大小的最简单方法。你可以这样做:在=新的BufferedReader

的BufferedReader(新的FileReader( “foo.in”),1024);

in.readLine(); 
in.readLine(); 
in.readLine(); 
in.readLine(); 
String line = in.readLine(); 
0

如果性能是这里的大问题,你经常从一个静态文件中读取随机线,那么你可以通过该文件的起始阅读和建立索引(基本上只是一个long[])有点优化这个文件每一行的偏移量。

一旦你有了这个,你知道确切位置,跳转到文件中,然后你可以阅读到下一个换行符检索完整行。

2

1)读了用户选择的线路,

如果你只需要读取用户选择的线路一次或很少(如果该文件是足够小),那么你就必须从头开始逐行读取文件,直到您到达选定的行。

另一方面,如果您需要频繁读取用户选择的行,则应该建立行号和偏移量的索引。因此,例如,第42行对应于文件中的2347字节的偏移量。因此,理想情况下,您只能读取整个文件一次并存储索引 - 例如,在地图中,将行号用作键和偏移量作为值。

2)读取自 上次读取以来增加的新行数。我计划每10秒读一次这个文件。我有 行数,可以找到新的行号,但我需要 读取线

对于第二点,你可以简单地保存而不是保存当前行当前偏移到文件数量 - 但如果继续提供显着的绩效收益,继续构建指数肯定不会受到伤害。

  1. 使用RandomAccessFile.seek(长偏移量)的文件指针设置为最近保存的偏移量(确认文件是不是最近保存第一偏移长 - 如果不是,什么新东西已被追加)。
  2. 使用RandomAccessFile.readLine()来读取行的文件
  3. 呼叫RandomAccessFile.getFilePointer()来获取当前读取行之后偏移和可选放(currLineNo + 1,偏移量)入索引。
  4. 重复步骤2-3直到到达文件末尾。

但是,除非性能已经成问题或极有可能成为问题,否则不要过分关注性能优化。

+0

这看起来不错,今晚我回家后我会试试(今天不得不上班)谢谢 – NoLiver92 2013-04-25 07:40:36

0

这里是我读过一个文件的代码片断,每10行写一行,包括第一行到新文件(writer)。你可以随时用你想做的任何事情替换try部分。要更改要读取的行数,只需将if语句“lc.endsWith(”0“)”中的0更改为您想要读取的任何行。但是,如果在读取文件时正在写入文件,则此代码只能在运行此代码时与文件内包含的数据一起使用。

  LineNumberReader lnr = new LineNumberReader(new FileReader(new File(file))); 
      lnr.skip(Long.MAX_VALUE); 
      int linecount=lnr.getLineNumber(); 
      lnr.close(); 

     for (int i=0; i<=linecount; i++){ 

      //read lines 
      String line = bufferedReader.readLine(); 
      String lc = String.valueOf(i); 

      if (lc.endsWith("0")){ 

       try{ 

        writer.append(line+"\n"); 
        writer.flush(); 

        }catch(Exception ee){ 
       } 
      } 
     }