多个引号会导致 PipedOutputStream/OutputStreamWriter 失败



当我试图将OutputStream复制到InputStream时,我偶然发现了一个非常奇怪的PipedOutputStream行为。另请参阅如何以编程方式编写 nt:file

下面是一个小的单元测试方法:

@Test
public void pipeTest() {
    PipedInputStream pin = null;
    try {
        pin = new PipedInputStream();
        PipedOutputStream pout = new PipedOutputStream(pin);
        OutputStreamWriter writer = new OutputStreamWriter(pout);
        for (int i = 0; i < 100; i++) {
            writer.write(""Test";" + i + "n");
            // writer.write(""Test";" + """ + i + ""n");
        }
        writer.close();
        pout.close();
        System.out.print(IOUtils.toString(pin));
    } catch (IOException e) {
        System.out.print(e);
    } finally {
        IOUtils.closeQuietly(pin);
    }
}

这很好用,可以打印出 100 行。如果您取消注释第二个 write 语句并注释掉第一个语句,writer.close()就会卡住并且永远不会完成。第二组引号似乎有问题 ".有没有人知道为什么会这样以及如何规避它?

这与引号无关 - 与您正在写入的数据量有关。为了演示这一点,您可以完全摆脱编写器和循环,只需使用:

pout.write(new byte[1024]);

或者保留您现有的代码,但看到它有效(因为它写入 1000 字节):

writer.write("0123456789");

但这不会(因为它尝试写入 1100 字节):

writer.write("0123456789X");

这行得通 - 但如果你把它改成 1025,它会永远挂起......因为默认情况下,内部缓冲区的长度为 1024 字节,并且没有任何东西消耗流。(在你写完之前,你不会从pin阅读。由于没有任何东西消耗前 1024 个字节中的任何一个,因此没有地方放置第 1025 个字节,因此write块直到空间。

您可以:

  • 在构造PipedInputStream时更改管道尺寸,使其具有更大的缓冲区
  • 在写入时从管道读取 - 例如在单独的线程中。

PipedInputStream有一个内部缓冲区。默认情况下,缓冲区为 1024 字节,但您可以将不同的大小传递给 PipedInputStream 的构造函数。

当缓冲区已满时,写入与PipedInputStream块关联的PipedOutputStream,直到从后者读取足够的数据,以便缓冲区中有空间。

你的问题与双引号本身无关;只是当你添加双引号时,你写了更多的数据。

应仅在多线程代码中使用管道流(其中一个线程写入管道输出流,另一个线程从管道输入流读取),以避免这种可能的死锁。

Javadoc for PipedInputStream对此有一个明确的警告:

尝试从单个线程使用两个对象不是 建议使用,因为它可能会使线程死锁。

相关内容

  • 没有找到相关文章

最新更新