Java InputStream a Byte Array y ByteBuffer

1. Información general

En este tutorial rápido, veremos cómo convertir un InputStream en un byte [] y ByteBuffer , primero usando Java simple, luego usando Guava y Commons IO.

Este artículo es parte de la serie "Java - Back to Basic" aquí en Baeldung.

2. Convertir a matriz de bytes

Veamos cómo obtener una matriz de bytes a partir de flujos de entrada simples . El aspecto importante de una matriz de bytes es que permite un acceso indexado (rápido) a cada valor de 8 bits (un byte) almacenado en la memoria . Por lo tanto, puede manipular estos bytes para controlar cada bit. Vamos a ver cómo convertir un flujo de entrada simple en un byte [] - primero usando Java simple, luego usando Guava y Apache Commons IO.

2.1. Convertir usando Java simple

Comencemos con una solución de Java enfocada en tratar con un flujo de tamaño fijo:

@Test public void givenUsingPlainJava_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { InputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); byte[] targetArray = new byte[initialStream.available()]; initialStream.read(targetArray); }

En el caso de un flujo almacenado en búfer, donde estamos tratando con un flujo almacenado en búfer y no sabemos el tamaño exacto de los datos subyacentes, necesitamos hacer que la implementación sea más flexible:

@Test public void givenUsingPlainJavaOnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); // not really unknown ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; while ((nRead = is.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); byte[] byteArray = buffer.toByteArray(); }

Comenzando con Java 9, podemos lograr lo mismo con un método dedicado en InputStream :

@Test public void givenUsingPlainJava9_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); byte[] data = is.readAllBytes(); }

2.2. Convertir usando guayaba

Veamos ahora la solución simple basada en Guava, utilizando la conveniente clase de utilidad ByteStreams:

@Test public void givenUsingGuava_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { InputStream initialStream = ByteSource.wrap(new byte[] { 0, 1, 2 }).openStream(); byte[] targetArray = ByteStreams.toByteArray(initialStream); }

2.3. Convertir usando Commons IO

Y finalmente, una solución sencilla con Apache Commons IO:

@Test public void givenUsingCommonsIO_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { ByteArrayInputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); byte[] targetArray = IOUtils.toByteArray(initialStream); }

El método IOUtils.toByteArray () almacena en búfer la entrada internamente, por lo que no es necesario utilizar una instancia de BufferedInputStream cuando se necesita almacenamiento en búfer.

3. Convertir a ByteBuffer

Ahora, veamos cómo obtener un ByteBuffer de un InputStream. Esto es útil siempre que necesitemos realizar operaciones de E / S rápidas y directas de bajo nivel en la memoria .

Usando el mismo enfoque que las secciones anteriores, veremos cómo convertir un InputStream en un ByteBuffer , primero usando Java simple, luego usando Guava y Commons IO.

3.1. Convertir usando Java simple

En el caso de un flujo de bytes, conocemos el tamaño exacto de los datos subyacentes. Vamos a usar la ByteArrayInputStream # disponible método para leer el flujo de bytes en un ByteBuffer :

@Test public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { byte[] input = new byte[] { 0, 1, 2 }; InputStream initialStream = new ByteArrayInputStream(input); ByteBuffer byteBuffer = ByteBuffer.allocate(3); while (initialStream.available() > 0) { byteBuffer.put((byte) initialStream.read()); } assertEquals(byteBuffer.position(), input.length); }

3.2. Convertir usando guayaba

Veamos ahora una solución simple basada en Guava, utilizando la conveniente clase de utilidad ByteStreams :

@Test public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { InputStream initialStream = ByteSource .wrap(new byte[] { 0, 1, 2 }) .openStream(); byte[] targetArray = ByteStreams.toByteArray(initialStream); ByteBuffer bufferByte = ByteBuffer.wrap(targetArray); while (bufferByte.hasRemaining()) { bufferByte.get(); } assertEquals(bufferByte.position(), targetArray.length); }

Aquí usamos un ciclo while con el método hasRemaining para mostrar una forma diferente de leer todos los bytes en el ByteBuffer. De lo contrario, la aserción fallará porque la posición del índice ByteBuffer será cero.

3.3. Convertir usando Commons IO

Y finalmente, usando Apache Commons IO y la clase IOUtils :

@Test public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() throws IOException { byte[] input = new byte[] { 0, 1, 2 }; InputStream initialStream = new ByteArrayInputStream(input); ByteBuffer byteBuffer = ByteBuffer.allocate(3); ReadableByteChannel channel = newChannel(initialStream); IOUtils.readFully(channel, byteBuffer); assertEquals(byteBuffer.position(), input.length); }

4. Conclusión

Este artículo ilustró varias formas de convertir un flujo de entrada sin procesar en una matriz de bytes y un ByteBuffer utilizando Java simple, Guava y Apache Commons IO.

La implementación de todos estos ejemplos se puede encontrar en nuestro proyecto GitHub.