用InputStream包装ByteBuffer

Eri*_*rik 43 java nio bytebuffer inputstream

我有一个方法,它接受一个I​​nputStream并从中读取数据.我想将此方法与ByteBuffer一起使用.有没有办法包装ByteBuffer所以它可以作为流访问?

Mik*_*ton 69

Thilo提到的实现似乎存在一些错误,并且还会逐字复制并粘贴到其他网站上:

  1. ByteBufferBackedInputStream.read() 返回一个符号扩展int表示它读取的字节,这是错误的(值应该在范围[-1..255])
  2. ByteBufferBackedInputStream.read(byte[], int, int) 根据API规范,当缓冲区中没有剩余字节时,不返回-1

ByteBufferBackedOutputStream似乎相对健全.

我在下面提供一个"固定"版本.如果我发现更多错误(或有人指出它们),我会在这里更新它.

更新:synchronized从读/写方法中删除关键字

的InputStream

public class ByteBufferBackedInputStream extends InputStream {

    ByteBuffer buf;

    public ByteBufferBackedInputStream(ByteBuffer buf) {
        this.buf = buf;
    }

    public int read() throws IOException {
        if (!buf.hasRemaining()) {
            return -1;
        }
        return buf.get() & 0xFF;
    }

    public int read(byte[] bytes, int off, int len)
            throws IOException {
        if (!buf.hasRemaining()) {
            return -1;
        }

        len = Math.min(len, buf.remaining());
        buf.get(bytes, off, len);
        return len;
    }
}
Run Code Online (Sandbox Code Playgroud)

的OutputStream

public class ByteBufferBackedOutputStream extends OutputStream {
    ByteBuffer buf;

    public ByteBufferBackedOutputStream(ByteBuffer buf) {
        this.buf = buf;
    }

    public void write(int b) throws IOException {
        buf.put((byte) b);
    }

    public void write(byte[] bytes, int off, int len)
            throws IOException {
        buf.put(bytes, off, len);
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 也应该实现 `int available()` 。 (2认同)

Thi*_*ilo 14

JDK中没有任何东西,但有很多实现,谷歌为ByteBufferInputStream.基本上它们包装一个或多个ByteBuffers并跟踪它们的索引,记录已经读取了多少.像这样的东西出现了很多,但显然是有缺陷的,请参阅@Mike Houston对改进版本的回答).


Ebo*_*ike 7

如果它由字节数组支持,您可以使用a ByteArrayInputStream并获取字节数组via ByteBuffer.array().如果您在本机ByteBuffer上尝试它,这将抛出异常.

  • 只有在您确定要读取后备字节数组的全部内容时,此方法才有效.对于你有一个部分满的缓冲区的情况,你最终会超出限制. (6认同)
  • 这种方法是错误的,因为缓冲区内容可能只是数组的一部分,并且数组的开头和结尾将包含其他数据。请参见get()方法的实现。 (2认同)