Percy

Groovy:从文件读取一系列行

java

我有一个文本文件,其中包含大约2,000,000行的大量数据。使用以下代码片段浏览文件很容易,但这不是我所需要的;-)

def f = new File("input.txt")
f.eachLine() {
    // Some code here
}

我只需要从文件中读取特定范围的行。有没有办法像这样(伪代码)指定开始和结束行?在选择范围之前,我想避免使用readLines()将所有行加载到内存中。

// Read all lines from 4 to 48
def f = new File("input.txt")
def start = 4
def end = 48
f.eachLine(start, end) {
    // Some code here
}

如果Groovy无法做到这一点,那么也欢迎使用任何Java解决方案:-)


阅读 836

收藏
2020-12-06

共2个答案

小编典典

我不认为有任何“魔术”方法可以跳到文件中的任意“行”。行仅由换行符定义,因此,如果不实际读取文件,就无法知道行将在何处。我相信您有两种选择:

  1. 遵循Mark Peter的回答,并使用BufferedReader一次一行读取文件,直到到达所需的行。这显然很慢。
  2. 找出下一次读取需要从多少字节(而不是行)开始,并使用RandomAccessFile之类的东西直接寻找文件中的该点。是否可以有效地知道正确的字节数取决于您的应用程序。例如,如果要顺序读取文件,一次读取一个文件,则只需记录下一个停止的位置。如果所有行的长度都是固定的L字节,那么到达第N行只是寻找位置N * L的问题。如果您经常重复此操作,则一些预处理可能会有所帮助:例如,一次读取整个文件,并将每行的开始位置记录在内存中的HashMap中。下次您需要转到N行时,只需在HashMap中查找它的位置并直接寻找到该点即可。
2020-12-06
小编典典

Java解决方案:

BufferedReader r = new BufferedReader(new FileReader(f));
String line;
for ( int ln = 0; (line = r.readLine()) != null && ln <= end; ln++ ) {
    if ( ln >= start ) {
        //Some code here
    }
}

Gross, eh?

不幸的是,除非您的行是固定长度的,否则您将无法有效地跳到start第th行,因为每行都可能是任意长的,因此需要读取所有数据。但是,这并不排除更好的解决方案。

Java 8

认为值得进行更新以显示如何使用Streams有效地做到这一点:

int start = 5;
int end = 12;
Path file = Paths.get("/tmp/bigfile.txt");

try (Stream<String> lines = Files.lines(file)) {
    lines.skip(start).limit(end-start).forEach(System.out::println);
}

因为Streams是惰性计算的,所以它只会读取直到end(包括)的行(以及它选择执行的任何内部缓冲)。

2020-12-06