Lectura de una secuencia de entrada binaria en una única matriz de bytes en Java

La documentación dice que no se debe usar el método available() para determinar el tamaño de un InputStream . ¿Cómo puedo leer todo el contenido de un InputStream en una matriz de bytes?

 InputStream in; //assuming already present byte[] data = new byte[in.available()]; in.read(data);//now data is filled with the whole content of the InputStream 

Pude leer varias veces en un búfer de un tamaño fijo, pero luego, tendré que combinar los datos que leí en una única matriz de bytes, lo cual es un problema para mí.

El enfoque más simple de IMO es usar guayaba y su clase ByteStreams :

 byte[] bytes = ByteStreams.toByteArray(in); 

O para un archivo:

 byte[] bytes = Files.toByteArray(file); 

Alternativamente (si no desea usar Guava), puede crear un ByteArrayOutputStream , y leer repetidas veces en una matriz de bytes y escribir en ByteArrayOutputStream (permitiendo que maneje el cambio de tamaño), luego llamar a ByteArrayOutputStream.toByteArray() .

Tenga en cuenta que este enfoque funciona si puede saber la duración de su entrada o no, suponiendo que tenga suficiente memoria, por supuesto.

Si está leyendo desde un archivo, puede hacer algo como esto:

  File file = new File("myFile"); byte[] fileData = new byte[(int) file.length()]; DataInputStream dis = new DataInputStream(new FileInputStream(file)); dis.readFully(fileData); dis.close(); 

ACTUALIZACIÓN (31 de mayo de 2014):

Java 7 agrega algunas características nuevas en el paquete java.nio.file que se pueden usar para hacer que este ejemplo sea un poco más corto. Vea el método readAllBytes () en la clase java.nio.file.Files . Aquí hay un pequeño ejemplo:

 import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; // ... Path p = FileSystems.getDefault().getPath("", "myFile"); byte [] fileData = Files.readAllBytes(p); 

Tenga en cuenta que, en el momento de escribir estas líneas, la API de Android no es compatible con esto (ni mucho de nada en Java 7).

Puede usar Apache commons-io para esta tarea:

Consulte este método :

 public static byte[] readFileToByteArray(File file) throws IOException 

Actualizar:

Java 7 manera:

 byte[] bytes = Files.readAllBytes(Paths.get(filename)); 

y si es un archivo de texto y desea convertirlo a String (cambie la encoding según sea necesario):

 StandardCharsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString() 

Puede leerlo en trozos ( byte buffer[] = new byte[2048] ) y escribir los fragmentos en ByteArrayOutputStream. Desde ByteArrayOutputStream puede recuperar el contenido como un byte [], sin necesidad de determinar su tamaño de antemano.

Creo que la longitud del búfer debe especificarse, ya que la memoria es finita y puede quedarse sin ella

Ejemplo:

 InputStream in = new FileInputStream(strFileName); long length = fileFileName.length(); if (length > Integer.MAX_VALUE) { throw new IOException("File is too large!"); } byte[] bytes = new byte[(int) length]; int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) { offset += numRead; } if (offset < bytes.length) { throw new IOException("Could not completely read file " + fileFileName.getName()); } in.close(); 

El valor máximo para el índice de matriz es Integer.MAX_INT – tiene alrededor de 2 Gb (2 ^ 31/2 147 483 647). Su flujo de entrada puede ser más grande que 2Gb, por lo que debe procesar los datos en fragmentos, lo siento.

  InputStream is; final byte[] buffer = new byte[512 * 1024 * 1024]; // 512Mb while(true) { final int read = is.read(buffer); if ( read < 0 ) { break; } // do processing }