java - 用一个 BufferedReader 读取多个文件?
问题描述
所以我能够像这样读取现有文件:
File file = new File("C:\\Something/test.txt");
FileInputStream fis = new FileInputStream(file);
BufferedReader bfr = new BufferedReader(new InputStreamReader(fis));
现在我可以使用 bfr.readLine() 并逐行读取。如果我想读取另一个文件,我是否必须创建一个新的 BufferedReader 或者有什么方法可以使用一个 BufferedReader 读取多个文件?
解决方案
您可以使用SequenceInputStream
顺序读取文件。
File file1 = new File("C:\\Something/test1.txt");
File file2 = new File("C:\\Something/test2.txt");
FileInputStream fis1 = new FileInputStream(file1);
FileInputStream fis2 = new FileInputStream(file2);
SequenceInputStream is = new SequenceInputStream(fis1, fis2);
BufferedReader bfr = new BufferedReader(new InputStreamReader(is));
正确关闭流
要关闭这两个流(和阅读器),只需使用try-with-resources
:
try (
FileInputStream fis1 = new FileInputStream(file1);
FileInputStream fis2 = new FileInputStream(file2);
SequenceInputStream is = new SequenceInputStream(fis1, fis2);
BufferedReader bfr = new BufferedReader(new InputStreamReader(is))
) {
System.out.println(bfr.readLine());
System.out.println(bfr.readLine());
}
使用两个以上的流
如果有两个以上的流,我们必须使用接受sEnumeration
的构造函数。InputStream
正如@Boris the Spider 所提到的,这里的棘手部分是正确关闭所有流。我们可以创建一个Autoclosable
包含所有InputStream
要关闭的 s 的容器,但是在我们构造该容器之前,但在一些流已经构造之后,可能会发生异常,因此一些流将保持未关闭状态。
一种干净的方法是在try-with-resources
语句中明确包含所有流:
try (
FileInputStream fis1 = new FileInputStream(file1);
FileInputStream fis2 = new FileInputStream(file2);
FileInputStream fis3 = new FileInputStream(file3);
...
SequenceInputStream is = new SequenceInputStream(new IteratorEnumeration<>(Arrays.asList(fis1, fis2, fis3, ...).iterator()));
BufferedReader bfr = new BufferedReader(new InputStreamReader(is))
) {
// .. read from bfr
}
IteratorEnumeration
是https://stackoverflow.com/a/7086010/7637120中建议的
另一种选择是手动跟踪已成功打开的输入流列表,并在下一个流构建失败时关闭它们。
public class InputStreams implements AutoCloseable {
private final List<InputStream> streams = new ArrayList<>();
public List<InputStream> getStreams() {
return streams;
}
public void add(InputStream is) {
streams.add(is);
}
@Override
public void close() throws IOException {
IOException firstException = null;
for (InputStream stream : streams) {
try {
stream.close();
} catch (IOException e) {
if (firstException == null) {
firstException = e;
} else {
firstException.addSuppressed(e);
}
}
}
if (firstException != null) {
throw firstException;
}
}
}
InputStreams streams = new InputStreams();
while (moreStreams()) {
InputStream nextStream = null;
try {
nextStream = getNextStream();
streams.add(nextStream);
} catch (IOException e) {
// the following will close nextStream and all the earlier streams
try (InputStreams streamsToClose = streams) {
if (nextStream != null) {
nextStream.close();
}
} finally {
throw e;
}
}
}
try (
InputStreams streamsToClose = streams;
SequenceInputStream is = new SequenceInputStream(new IteratorEnumeration<>(streams.getStreams().iterator()));
BufferedReader bfr = new BufferedReader(new InputStreamReader(is))
) {
// work with bfr...
}
推荐阅读
- html - 从反转布尔禁用按钮
- ethereum - 在 web3.js 中设置最佳气体限制
- symfony - Symfony 4:ArrayCollection 添加不在数据库中
- javascript - TDD 和参数验证 Javascript
- c# - XML 的 xsi:nil 不反序列化为 null
- gradle - gradle: disable creation of the build folder at root in multi-projects application
- ruby-on-rails - 从外部网络访问 Puma
- c# - 异步命令 Wpf C#
- yii2 - Yii2 使用 when 验证器通过第二个模型进行验证
- java - 如何向 SAML/SOAP 请求添加标头