当我尝试将PipedOutputStream
复制到OutputStream
时,我偶然发现InputStream
的一个非常奇怪的行为。另请参阅How to write an nt:file programmatically
这是一个小单元测试方法:
@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行。如果取消注释第二个写入语句并注释掉第一个,writer.close()
会卡住并且永远不会完成。它似乎与第二组引号\"
有问题。
有没有人知道为什么会这样,以及如何规避它?
答案 0 :(得分:3)
这与引号无关 - 而且与您正在编写的数据量有关。为了证明这一点,你可以完全摆脱编写器和循环,只需使用:
pout.write(new byte[1024]);
或保留现有代码,但看到这有效(因为它写了1000个字节):
writer.write("0123456789");
但这没有(因为它试图写1100字节):
writer.write("0123456789X");
可行 - 但是如果你将它改为1025,它将永远挂起......因为默认情况下内部缓冲区长度为1024字节,并且没有任何消耗流。 (在完成写入之前,你不会从pin
读取。)由于没有任何消耗前1024个字节中的任何一个,所以无处放置第1025个字节,所以write
阻塞直到是空间。
你可以:
PipedInputStream
时更改管道大小,因此它有一个更大的缓冲区答案 1 :(得分:0)
PipedInputStream
有一个内部缓冲区。默认情况下,缓冲区为1024字节,但您可以将不同的大小传递给PipedInputStream
的构造函数。
当缓冲区已满时,写入与PipedOutputStream
块关联的PipedInputStream
,直到您从后者读取足够的数据,以便缓冲区中有空间
你的问题与双引号本身无关;它只是你添加双引号时写的更多数据。
您应该只在多线程代码中使用管道流(其中一个线程写入管道输出流,另一个线程从管道输入流中读取),以避免这种可能的死锁。
PipedInputStream
的Javadoc对此有明确警告:
尝试同时使用单个线程中的两个对象 建议,因为它可能使线程死锁。