当我试图将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
对此有一个明确的警告:
尝试从单个线程使用两个对象不是 建议使用,因为它可能会使线程死锁。