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行。
答案 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)
是另一种选择,直接给出了这条线,但对我的情况没有帮助。