为什么Charbuffer的“管道”挂起?

时间:2008-09-24 15:03:59

标签: java io pipe

为什么以下方法会挂起?

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
    }
}

3 个答案:

答案 0 :(得分:1)

回答我自己的问题:你必须在buf.clear()之间致电read。据推测,read因为缓冲区已满而挂起。正确的代码是

public void pipe(Reader in, Writer out) {
    CharBuffer buf = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
    while( in.read(buf) >= 0 ) {
      out.append(buf.flip());
      buf.clear();
    }
}

答案 1 :(得分:0)

我认为这是一个僵局。 in.read(buf)锁定CharBuffer并阻止out.append(buf)调用。

假设CharBuffer在实现中使用了锁(某种)。 API对CharBuffer类有什么看法?

编辑:对不起,我脑子里有某种短路......我把它与其他东西混淆了。

答案 2 :(得分:0)

CharBuffers不像你期望的那样干净利落地与读者和作家合作。特别是,没有Writer.append(CharBuffer buf)方法。问题代码段调用的方法是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实现也会更好。