Maneras sencillas de escribir un InputStream de Java en un OutputStream

1. Información general

En este tutorial rápido, aprenderemos cómo escribir un InputStream de Java en un OutputStream de Java . Primero usaremos la funcionalidad principal de Java 8 y Java 9. Luego, veremos un par de bibliotecas externas: Guava y la biblioteca IO de Apache Commons.

Los métodos de utilidad proporcionados por Java 9, Guava y Apache Commons IO no vacían ni cierran los flujos. Entonces, necesitaremos administrar estos recursos usando try-with-resources o un bloque finalmente .

2. Usando Java 8

Primero, comenzaremos por crear un método simple usando Java vanilla para copiar el contenido de InputStream a OutputStream :

void copy(InputStream source, OutputStream target) throws IOException { byte[] buf = new byte[8192]; int length; while ((length = source.read(buf)) > 0) { target.write(buf, 0, length); } }

Este código es bastante sencillo: simplemente leemos algunos bytes y luego los escribimos.

3. Usando Java 9

Java 9 proporciona un método de utilidad, InputStream.transferTo () , para esta tarea .

Veamos cómo usaríamos el método transferTo () :

@Test public void givenUsingJavaNine_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException { String initialString = "Hello World!"; try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes()); ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) { inputStream.transferTo(targetStream); assertEquals(initialString, new String(targetStream.toByteArray())); } }

Tenga en cuenta que cuando se trabaja con flujos de archivos, es más eficiente usar Files.copy () que el método transferTo () .

4. Usando guayaba

A continuación, veamos cómo usaríamos el método de utilidad ByteStreams.copy () de Guava .

Necesitaremos incluir la dependencia de guayaba en nuestro pom.xml :

 com.google.guava guava 29.0-jre 

Creemos un caso de prueba simple para mostrar cómo podríamos usar ByteStreams para copiar datos:

@Test public void givenUsingGuava_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException { String initialString = "Hello World!"; try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes()); ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) { ByteStreams.copy(inputStream, targetStream); assertEquals(initialString, new String(targetStream.toByteArray())); } }

5. Uso de Commons IO

Finalmente, veamos cómo usaríamos el método Commons IO IOUtils.copy () para esta tarea.

Por supuesto, necesitaremos agregar la dependencia commons-io al pom.xml :

 commons-io commons-io 2.7 

Creemos un caso de prueba simple usando IOUtils para copiar datos del flujo de entrada al flujo de salida:

@Test public void givenUsingCommonsIO_whenCopyingInputStreamToOutputStream_thenCorrect() throws IOException { String initialString = "Hello World!"; try (InputStream inputStream = new ByteArrayInputStream(initialString.getBytes()); ByteArrayOutputStream targetStream = new ByteArrayOutputStream()) { IOUtils.copy(inputStream, targetStream); assertEquals(initialString, new String(targetStream.toByteArray())); } }

Nota: Commons IO proporciona métodos adicionales para trabajar con InputStream sy OutputStream s. IOUtils.copyLarge () debe usarse siempre que sea necesario copiar 2 GB o más de datos.

6. Conclusión

En este artículo, exploramos formas sencillas de copiar datos de un InputStream a un OutputStream .

La implementación de estos ejemplos está disponible en GitHub.