如何以不连续的顺序读取文件

时间:2018-02-08 02:07:28

标签: java java-8

file.txt有10行

Integer[] lineWanted ={2,5,1};
BufferedReader br = new BufferedReader(new FileReader("file.txt"));

for (int i = 0; i < lineWanted.length; i++) {
        List<String> lineList = br.lines()
                .skip(indexes[i]-1)
                .limit(1)
                .collect(Collectors.toList());

            System.out.println(lineList);
}

但代码正在跳过行然后计数。      即O / P获取的是第2,7和8行。

4 个答案:

答案 0 :(得分:1)

如果您坚持这样做,请仔细查看skip(和limit)正在做什么。您正在跳过所需的行索引,但是从文件中的当前位置跳转。即,你正确地到达第2行,然后跳过5行(实际上是来自skip的4和来自limit的1)。这使你在7,你得到一行到8。

实现这一目标的“正确”方法是预先排序lineWanted,跟踪先前的索引,并增加当前和先前索引之间的差异。但是,正如@tsolakp指出的那样,多次调用lines实际上是一个未定义的操作:你不应该这样做。

答案 1 :(得分:1)

BufferedReader.lines()的规范清楚地表明,在处理Stream之后,BufferedReader处于未定义状态,之后无法使用。因此,除非您有充分的理由使用BufferedReader,否则建议使用Files.lines从文件中获取行流,这样可以防止任何尝试首先重用基础读取器。< / p>

您可以通过重复创建新流来实现目标,但这会带来不可接受的开销。请记住,即使您跳过行,仍然必须处理文件内容,以便在跳过行之前识别行边界。与计算相比,I / O操作通常很昂贵。

折衷方案是首先确定所需的最大行号,以避免处理超过必要的行(通过limit)和最小所需行号,以避免不必要的中间存储(通过skip)收集到临时List的单个Stream操作。这可能暂时在最小值和最大值之间保留一些不需要的线,但在大多数情况下比基于I / O的多个Stream操作更有效:

int[] lineWanted = {2, 5, 1};
IntSummaryStatistics iss = Arrays.stream(lineWanted).summaryStatistics();

List<String> lineList;
try(Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    lineList = lines
        .limit(iss.getMax()+1).skip(iss.getMin())
        .collect(Collectors.toList());
}
lineList = Arrays.stream(lineWanted)
    .map(i -> i-iss.getMin())
    .mapToObj(lineList::get)
    .collect(Collectors.toList());

System.out.println(lineList);

答案 2 :(得分:0)

如果你真的无法对你的lineWanted列表进行排序,最好的方法可能是将整个文档缓冲到String []行,但这一切都取决于你想如何访问数据。您是想从一个文档中只读几行,还是只是按随机顺序阅读整个文档?

答案 3 :(得分:-1)

只需要在循环中移动BR(没有更好的选项能够找到,因为想用BufferedReader来做)。

Files.readAllLines(path).get(lineNo) 是另一种选择,直接给出了这条线,但对我的情况没有帮助。