我试图读取一个文本文件两次,以计算平均值(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()
方法,但这引发了一个不支持这些方法的异常。
我可以将整个文件读取到List对象中,然后使用它来计算这两个步骤,但我不知道我的文件会有多大,所以如果可能的话,我想尝试使用下面的方法找到解决方案。
有人知道我该怎么做吗?
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));
}
}
我认为您不应该使用try with resources。它在其BufferedReader上调用close
,导致所有封装的读取器关闭。即关闭BufferedReader
、Reader
和FileReader
。
当您在App::runProcess
中调用calcAverage
时,它会关闭所有读卡器。然后,在下一行调用processFile
时,您正试图读取已关闭的Reader
。