5

我正在尝试从文本文件中读取特定行,但是我不想将文件加载到内存中(它会变得非常大)。

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

我想做的一个例子:

String line = File.getLine(5);

“代码不是实际的代码,它是为了显示我想要的原理而编造的”

有没有办法做到这一点?

- - -编辑 - - -

我刚刚意识到这个文件也将被写入读取行之间(添加到文件末尾)。

4

8 回答 8

12

有没有办法做到这一点?

除非每行都有固定数量的字节,否则不会。

您实际上不必每一行都保存在内存中 - 但您必须通读整个文件才能找到您想要的行,否则您将不知道从哪里开始阅读。

于 2013-04-24T20:00:15.067 回答
4

必须逐行读取文件。否则,您怎么知道何时到达第 5 行(如您的示例中所示)?

编辑:

正如 Jon Skeet 所说,您可能还想查看Random Access Files,如果您知道每行有多少字节,这可能会有所帮助。

于 2013-04-24T20:00:22.807 回答
3

最简单的方法是使用 BufferedReader ( http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedReader.html ),因为您可以指定缓冲区大小。您可以执行以下操作:

BufferedReader in = new BufferedReader(new FileReader("foo.in"), 1024);

in.readLine();
in.readLine();
in.readLine();
in.readLine();
String line = in.readLine();
于 2013-04-24T20:08:41.667 回答
2

1)读取用户选择的一行,

如果您只需要一次或不经常读取用户选择的行(或者如果文件足够小),那么您只需从头开始逐行读取文件,直到到达所选行。

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

2) 读取自上次读取后添加的新行。我计划每 10 秒读取一次文件。我有行数,可以找出新的行号,但我需要阅读该行

对于第二点,您可以简单地将当前偏移量保存到文件中,而不是保存当前行号——但如果它继续提供显着的性能优势,继续构建索引肯定不会有什么坏处。

  1. 使用 RandomAccessFile.seek(long offset) 将文件指针设置为最近保存的偏移量(首先确认文件比最近保存的偏移量长——如果不是,则没有附加任何新内容)。
  2. 使用 RandomAccessFile.readLine() 读取文件的一行
  3. 在读取行后调用 RandomAccessFile.getFilePointer() 以获取当前偏移量,并可选择将(currLineNo+1, offset) 放入索引中。
  4. 重复步骤 2-3,直到到达文件末尾。

但是,除非性能已经是一个问题或者很可能是一个问题,否则不要对性能优化太过分了。

于 2013-04-25T04:39:22.970 回答
1

对于小文件:

String line = Files.readAllLines(Paths.get("file.txt")).get(n);

对于大文件:

String line;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    line = lines.skip(n).findFirst().get();
}

爪哇 7:

String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    for (int i = 0; i < n; i++)
        br.readLine();
    line = br.readLine();
}

资料来源:从文件中读取第 n 行

于 2018-12-10T10:09:44.420 回答
0

做到这一点的唯一方法是建立每行所在位置的索引(您只需要记录每行的结尾)如果无法从一开始就根据索引随机访问一行,则必须读取每个字节在那条线之前。

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

于 2013-04-24T20:04:26.837 回答
0

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

一旦你有了这个,你就知道在文件中跳转到哪里,然后你可以读到下一个换行符来检索整行。

于 2013-04-24T20:19:34.657 回答
0

这是我拥有的一些代码片段,它将读取一个文件并将包括第一行在内的每 10 行写入一个新文件(编写器)。您始终可以将 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){
                }
            }
        }
于 2017-11-15T16:54:18.087 回答