我尝试读取文本文件两次,以计算平均值(calcAverage),然后根据平均值进行过滤,得到结果列表(processFile)。当第二步运行异常时,
抛出java.io.UncheckedIOException: java.io.IOException: Stream closed。
下面是我失败代码的简化版本和驱动代码的单元测试。
Reader类型的参数(source)从单元测试传递到App,它是文本文件的FileReader。我不知道如何从Reader对象访问File处理程序(或文件名)来重新打开它-我已经尝试在应用程序中实现了这一点,这将解决这个问题。runProcess (Reader source)的方法签名不能更改,但其他方法签名可以更改。
我使用一个try-with-resources块打开Reader对象并读取它--然后自动关闭--这一切都很好。我只需要一种从Reader重新打开文件的方法来执行pass-2过滤。
我从类似的问题中读到过,BufferedReader就像一个迭代器,你只能读它一次。
我尝试在我的source对象上使用mark()和reset()方法,但是抛出了一个不支持这些方法的异常。
我可以将整个文件读取到一个列表对象中,然后使用它来计算这两个步骤,但我不知道我的文件将有多大,所以如果可能的话,我想尝试使用下面的方法找到解决方案。
有人知道我如何实现它吗?
public class App {
public static void runProcess(Reader source) {
Collection<?> col = calcAverage(source);
processFile(source).forEach(x -> System.out.println(x));
}
private static Collection processFile(Reader source) {
Collection<?> col = processFile(source, ((BufferedReader reader) -> reader.lines()
.skip(1)
.collect(Collectors.toList()))
);
return col;
}
private static Collection<?> calcAverage(Reader source) {
Collection<?> col = processFile(source, ((BufferedReader reader) -> reader.lines()
.skip(1)
.collect(Collectors.toList())));
return col;
}
private static Collection<?> processFile(Reader source, BufferedReaderProcessor p){
try (BufferedReader reader = new BufferedReader(source)) {
return p.process(reader);
}catch (FileNotFoundException f){
f.printStackTrace();
return null;
}catch (IOException e){
e.printStackTrace();
return null;
}catch (Exception ex){
ex.printStackTrace();
return null;
}
}
@FunctionalInterface
public interface BufferedReaderProcessor {
Collection<?> process(BufferedReader b) throws IOException;
}
} public class AppTest {
@Test
public void shouldReadFileTwice() throws FileNotFoundException {
App.runProcess(openFile("src/main/java/functions/example4/resources/list-of-fruits"));
}
private static Reader openFile(String filename) throws FileNotFoundException {
return new FileReader(new File(filename));
}
} 发布于 2020-11-27 00:46:22
我相信你不应该对资源使用try。它在其BufferedReader上调用close,这会导致关闭所有封装的读取器。即关闭BufferedReader、Reader和FileReader。
当您在App::runProcess中调用calcAverage时,它会关闭所有读取器。然后,当在下一行调用processFile时,您将尝试读取closed Reader。
https://stackoverflow.com/questions/64684948
复制相似问题