使用一个BufferedReader读出多个文件?

时间:2018-05-12 19:31:55

标签: java

所以我能够读出这样的现有文件:

    File file = new File("C:\\Something/test.txt");
    FileInputStream fis = new FileInputStream(file);
    BufferedReader bfr = new BufferedReader(new InputStreamReader(fis));

现在我可以使用bfr.readLine()并逐行读取。 如果我想读出另一个文件,我是否必须创建一个新的BufferedReader,或者有没有办法用一个BufferedReader读出多个文件?

1 个答案:

答案 0 :(得分:2)

您可以使用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());
    }

使用两个以上的流

如果有两个以上的流,我们必须使用接受EnumerationInputStream的构造函数。正如@Boris the Spider所提到的,这里棘手的部分正在关闭所有流。我们可以创建一个Autoclosable来包含要关闭的所有InputStream,但是在构造该容器之前,但是在构建了一些流之后,可能会发生异常,所以有些流将保持未公开状态。

一种干净的方法是在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
    }

IteratorEnumerationhttps://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...
}