Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping a ByteBuffer with an InputStream

I have a method that takes an InputStream and reads data from it. I would like to use this method with a ByteBuffer also. Is there a way to wrap a ByteBuffer so it can be accessed as a stream?

like image 923
Erik Avatar asked Dec 02 '10 06:12

Erik


People also ask

What does ByteBuffer wrap do?

wrap. Wraps a byte array into a buffer. The new buffer will be backed by the given byte array; that is, modifications to the buffer will cause the array to be modified and vice versa. The new buffer's capacity and limit will be array.

How do you write InputStream to ByteArrayOutputStream?

InputStream is; byte[] bytes = IOUtils. toByteArray(is); Internally this creates a ByteArrayOutputStream and copies the bytes to the output, then calls toByteArray() . It handles large files by copying the bytes in blocks of 4KiB.

How do you read all bytes from InputStream?

Since Java 9, we can use the readAllBytes() method from InputStream class to read all bytes into a byte array. This method reads all bytes from an InputStream object at once and blocks until all remaining bytes have read and end of a stream is detected, or an exception is thrown.

How do I allocate ByteBuffer?

A new ByteBuffer can be allocated using the method allocate() in the class java. nio. ByteBuffer. This method requires a single parameter i.e. the capacity of the buffer.


1 Answers

There seem to be some bugs with the implementation referred to by Thilo, and also copy and pasted on other sites verbatim:

  1. ByteBufferBackedInputStream.read() returns a sign extended int representation of the byte it reads, which is wrong (value should be in range [-1..255])
  2. ByteBufferBackedInputStream.read(byte[], int, int) does not return -1 when there are no bytes remaining in the buffer, as per the API spec

ByteBufferBackedOutputStream seems relatively sound.

I present a 'fixed' version below. If I find more bugs (or someone points them out) I'll update it here.

Updated: removed synchronized keywords from read/write methods

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;     } } 

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);     }  } 
like image 126
Kothar Avatar answered Sep 24 '22 10:09

Kothar