Lendo um stream de input binário em uma matriz de bytes única em Java

A documentação diz que não se deve usar o método available() para determinar o tamanho de um InputStream . Como posso ler todo o conteúdo de um InputStream em uma 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 

Eu poderia ler várias vezes em um buffer de um tamanho fixo, mas, então, terei que combinar os dados que eu li em uma única matriz de bytes, o que é um problema para mim.

A abordagem mais simples do IMO é usar a class Guava e ByteStreams :

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

Ou para um arquivo:

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

Alternativamente (se você não quisesse usar o Guava), você poderia criar um ByteArrayOutputStream , e ler repetidamente em uma matriz de bytes e escrever no ByteArrayOutputStream (permitindo que o redimensionamento fosse manipulado), então chamar ByteArrayOutputStream.toByteArray() .

Note que esta abordagem funciona se você pode dizer o comprimento de sua input ou não – supondo que você tenha memory suficiente, é claro.

Se você está lendo de um arquivo, você pode fazer algo assim:

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

ATUALIZAÇÃO (31 de maio de 2014):

O Java 7 adiciona alguns novos resources no pacote java.nio.file que podem ser usados ​​para tornar este exemplo algumas linhas mais curtas. Veja o método readAllBytes () na class java.nio.file.Files . Aqui está um pequeno exemplo:

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

Observe que, até o momento desta publicação, a API do Android não suporta isso (ou muito de qualquer coisa no Java 7).

Você pode usar o Apache commons-io para esta tarefa:

Consulte este método :

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

Atualizar:

Java 7 :

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

e se for um arquivo de texto e você quiser convertê-lo em String (altere a codificação conforme necessário):

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

Você pode lê-lo por blocos ( byte buffer[] = new byte[2048] ) e escrever os pedaços em um ByteArrayOutputStream. A partir do ByteArrayOutputStream você pode recuperar o conteúdo como um byte [], sem precisar determinar seu tamanho antecipadamente.

Eu acredito que o tamanho do buffer precisa ser especificado, já que a memory é finita e você pode ficar sem ela

Exemplo:

 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(); 

O valor máximo para o índice da matriz é Integer.MAX_INT – está em torno de 2Gb (2 ^ 31/2 147 483 647). Seu stream de input pode ser maior que 2Gb, então você tem que processar os dados em pedaços, desculpe.

  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 }