【发布时间】:2008-09-24 15:03:58
【问题描述】:
为什么下面的方法会挂起?
公共无效管道(读入,写出){ CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE); 而(in.read(buf)>= 0){ out.append(buf.flip()); } }【问题讨论】:
为什么下面的方法会挂起?
公共无效管道(读入,写出){ CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE); 而(in.read(buf)>= 0){ out.append(buf.flip()); } }【问题讨论】:
回答我自己的问题:您必须在reads 之间致电buf.clear()。据推测,read 挂起是因为缓冲区已满。正确的代码是
【讨论】:
我认为这是一个死锁。 in.read(buf) 锁定 CharBuffer 并阻止 out.append(buf) 调用。
假设 CharBuffer 在实现中使用了(某种)锁。 API 对 CharBuffer 类有何看法?
编辑:抱歉,我的大脑短路了……我把它和别的东西弄混了。
【讨论】:
CharBuffers 与 Readers 和 Writers 的工作并不像您预期的那样干净。特别是,没有Writer.append(CharBuffer buf) 方法。问题sn-p调用的方法是Writer.append(CharSequence seq),它只是调用了seq.toString()。 CharBuffer.toString() 方法确实返回缓冲区的字符串值,但它不会耗尽缓冲区。随后对Reader.read(CharBuffer buf) 的调用获得了一个已满的缓冲区,因此返回 0,从而强制循环无限期地继续。
虽然这感觉像是挂起,但实际上它是在每次通过循环时将第一次读取的缓冲区内容附加到写入器。因此,您要么开始在目标中看到大量输出,要么写入器的内部缓冲区会增长,具体取决于写入器的实现方式。
尽管很烦人,但我建议使用 char[] 实现,前提是因为 CharBuffer 解决方案每次通过循环都会构建至少两个新的 char[]。
public void pipe(Reader in, Writer out) throws IOException {
char[] buf = new char[DEFAULT_BUFFER_SIZE];
int count = in.read(buf);
while( count >= 0 ) {
out.write(buf, 0, count);
count = in.read(buf);
}
}
我建议您仅在需要支持两种字符编码之间的转换时才使用此方法,否则即使您正在传输字符,也最好使用 ByteBuffer/Channel 或 byte[]/IOStream 实现。
【讨论】: