如何复制BufferedReader?

16

我正在使用 BufferedReader 构造函数来创建一个现有 BufferedReader 的新副本。

BufferedReader buffReader = new BufferedReader(originalBuffReader);

新的buffReader工作正常,但当我执行originalBuffReader.readLine()时,它会返回null。是否有其他方法可以创建一个新的bufferReader而不影响我的原始BufferedReader

附:我将bufferReader作为输入传递给我的方法,并且我无法访问源代码。


你所说的“BufferedReader 的副本”是什么意思?你希望能够以某种方式两次读取相同的流吗?这是不可能的。事实上,这是一个自相矛盾的说法。 - user207421
3个回答

17
任何其他方法可以创建一个新的BufferReader而不影响我的原始BufferReader吗?
没有直接的方法只是通过创建两个BufferedReader来解决它。(这两个读取器将从同一源消耗数据。)您将不得不在源上添加另一层缓冲,以便每个读取器可以独立地读取流。
这可以通过结合Apache Commons中的TeeInputStreamPipedInputStreamPipedOutputStream来实现。
import java.io.*;
import org.apache.commons.io.input.TeeInputStream;
class Test {
    public static void main(String[] args) throws IOException {

        // Create the source input stream.
        InputStream is = new FileInputStream("filename.txt");

        // Create a piped input stream for one of the readers.
        PipedInputStream in = new PipedInputStream();

        // Create a tee-splitter for the other reader.
        TeeInputStream tee = new TeeInputStream(is, new PipedOutputStream(in));

        // Create the two buffered readers.
        BufferedReader br1 = new BufferedReader(new InputStreamReader(tee));
        BufferedReader br2 = new BufferedReader(new InputStreamReader(in));

        // Do some interleaved reads from them.
        System.out.println("One line from br1:");
        System.out.println(br1.readLine());
        System.out.println();

        System.out.println("Two lines from br2:");
        System.out.println(br2.readLine());
        System.out.println(br2.readLine());
        System.out.println();

        System.out.println("One line from br1:");
        System.out.println(br1.readLine());
        System.out.println();
    }
}

输出:

One line from br1:
Line1: Lorem ipsum dolor sit amet,      <-- reading from start

Two lines from br2:
Line1: Lorem ipsum dolor sit amet,      <-- reading from start
Line2: consectetur adipisicing elit,

One line from br1:
Line2: consectetur adipisicing elit,    <-- resumes on line 2

感谢aioobe的回复,实际上我正在将一个bufferReader作为我的方法输入,所以我必须使用该bufferReader进行复制,而无法访问源。 - Sunil
然后我会创建一个包装器,它包装给定的缓冲读取器,缓冲读取行并分配辅助读取器,这些读取器从缓冲区中读取。(除非您有将数据完全排放到List<String>中并使用该列表的选项。)(我很好奇,哪个API只给您提供了BufferedReader?) - aioobe
1
BufferReader是从某个地方填充的,并作为参数通过一个方法传递,我必须从那里取出它。 - Sunil
3
请注意复制粘贴此代码。这并非在任何情况下都有效。 例如,如果InputStream来自于ClassLoader.getSystemResourceAsStream("myResource"),它会卡住。 - Zarathustra

3
以下是一种考虑从原始BufferedReader创建新的BufferedReader的方法。
基本上,我们将原始buffered reader的内容转储到一个字符串中,然后重新创建一个新的BufferedReader对象。为了能够第二次重新读取原始BufferedReader,您可以标记它,然后在读取后重置它。
需要注意的一件事是,您可能需要保护免受DDOS攻击,其中一个非常大的缓冲读取器可能会出现,并且您可能希望避免永久读取并填充内存,您可以在某个点或满足某些条件时基本上在for循环后中断或退出。
final String originalBufferedReaderDump;
originalBufferedReaderDump.mark(Integer.MAX_VALUE);
for (String line; (line = originalBufferedReader.readLine()) != null; originalBufferedReaderDump+= line);
originalBufferedReader.reset();
final BufferedReader copiedBufferedReader  = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(originalBufferedReaderDump.getBytes())));

2
在构造新的BufferedReader时,将BufferedReader实例传递给构造函数不会复制原始BufferedReader!您正在执行的操作是链接两个读取器,换句话说,您正在缓冲已经缓冲的读取器实例。当您在buffReader上调用readLine()时,它将在originalBuffReader上调用readLine()。点击这里了解更多有关流链接的详细信息:流链接

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接