Groovy:从文件中读取一系列行

Rob*_*uch 13 java file-io groovy

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

def f = new File("input.txt")
f.eachLine() {
    // Some code here
}
Run Code Online (Sandbox Code Playgroud)

我只需要从文件中读取特定范围的行.有没有办法像这样指定起始和结束行(伪代码)?在选择范围之前,我想避免使用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
}
Run Code Online (Sandbox Code Playgroud)

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

干杯,罗伯特

Mar*_*ers 8

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
    }
}
Run Code Online (Sandbox Code Playgroud)

总,呃?

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

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);
}
Run Code Online (Sandbox Code Playgroud)

因为Streams被懒惰地评估,所以它只会读取和包括的行end(加上它选择做的内部缓冲).

  • @ smartnut007:你是因为那个而投票吗?首先,Java是有效的Groovy代码.其次,OP专门要求Java备选方案,问题首先用Java标记.认为你有更好的答案并不是一个很好的理由来贬低他人.如果你的更好,那将通过upvotes解决.如果出现问题,请进行投票. (6认同)

Dón*_*nal 5

这是一个 Groovy 解决方案。不幸的是,这将在之后读取文件的每一行start

def start = 4
def end = 48

new File("input.txt").eachLine(start) {lineNo, line ->

    if (lineNo <= end) {
        // Process the line
    }
}
Run Code Online (Sandbox Code Playgroud)


Yev*_*man 3

我不相信有任何“神奇”的方法可以跳到文件中的任意“行”。行仅由换行符定义,因此如果不实际读取文件,就无法知道这些行在哪里。我相信你有两个选择:

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