Classes ByteArrayInputStream e ByteArrayOutputStream em Java
Java oferece as classes ByteArrayInputStream
e ByteArrayOutputStream
para trabalhar com arrays de bytes diretamente na memória. Elas permitem tratar um array como uma fonte de dados (stream de entrada) ou como um destino (stream de saída), eliminando a necessidade de interagir com o sistema de arquivos. Essa abordagem é ideal para manipular dados que já estão na RAM, criar buffers intermediários ou facilitar testes unitários.
Leitura de um Array de Bytes com ByteArrayInputStream
A classe ByteArrayInputStream
representa um stream de entrada que utiliza um array de bytes como sua fonte. Seus construtores mais comuns são:
ByteArrayInputStream(byte[] buf)
ByteArrayInputStream(byte[] buf, int offset, int length)
O primeiro construtor cria um stream que lê o array buf
do início ao fim. O segundo permite especificar um ponto de partida (offset
) e a quantidade de bytes a serem lidos (length
) a partir desse array.
O exemplo a seguir demonstra como ler dados de dois arrays de bytes:
import java.io.*;
public class Program {
public static void main(String[] args) {
// Exemplo 1: Lendo um array de bytes numéricos
byte[] array1 = new byte[]{1, 3, 5, 7};
ByteArrayInputStream byteStream1 = new ByteArrayInputStream(array1);
int b;
while ((b = byteStream1.read()) != -1) {
System.out.println(b);
}
System.out.println("------");
// Exemplo 2: Lendo os 5 primeiros bytes de uma string
String text = "Hello world!";
byte[] array2 = text.getBytes();
// Cria um stream que lê apenas os 5 primeiros bytes ("Hello")
ByteArrayInputStream byteStream2 = new ByteArrayInputStream(array2, 0, 5);
int c;
while ((c = byteStream2.read()) != -1) {
System.out.print((char) c);
}
System.out.println();
}
}
Uma característica fundamental do ByteArrayInputStream
é que ele opera inteiramente em memória. Diferentemente de streams que gerenciam recursos do sistema (como arquivos), não existem recursos externos a serem liberados. Portanto, chamar o método close()
nesta classe não tem nenhum efeito.
Escrita para um Array de Bytes com ByteArrayOutputStream
A classe ByteArrayOutputStream
representa um stream de saída que utiliza um array de bytes interno e dinâmico como destino. Os dados escritos nele são armazenados em um buffer que cresce automaticamente conforme necessário.
Seus construtores são:
ByteArrayOutputStream()
ByteArrayOutputStream(int size)
A primeira versão cria um buffer interno com capacidade inicial de 32 bytes. A segunda permite especificar um tamanho inicial customizado (size
) para otimizar a alocação de memória.
Veja um exemplo de seu uso:
import java.io.*;
public class Program {
public static void main(String[] args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String text = "Hello World!";
byte[] buffer = text.getBytes();
try {
baos.write(buffer);
} catch (IOException ex) {
// A assinatura do método write() exige o catch, mas na prática
// ByteArrayOutputStream não lança IOException.
System.out.println(ex.getMessage());
}
// Recupera os dados como uma string (usando o charset padrão)
System.out.println("toString(): " + baos.toString());
// Recupera os dados como um array de bytes e os imprime
byte[] array = baos.toByteArray();
System.out.print("toByteArray(): ");
for (byte b : array) {
System.out.print((char) b);
}
System.out.println();
}
}
Os dados escritos no ByteArrayOutputStream
são mantidos em seu buffer interno. Para acessá-los, podem ser utilizados os métodos toString()
(que decodifica os bytes para uma string) e toByteArray()
. É importante notar que toByteArray()
retorna uma cópia dos bytes, garantindo que o buffer interno do stream não seja modificado externamente.
Além disso, o método writeTo(OutputStream out)
oferece uma maneira eficiente de transferir todo o conteúdo do buffer interno para outro stream de saída, como um FileOutputStream
.
// Supondo que 'baos' já contém os dados do exemplo anterior
try (FileOutputStream fos = new FileOutputStream("hello.txt")) {
baos.writeTo(fos);
System.out.println("Data has been written to hello.txt");
} catch (IOException e) {
System.out.println(e.getMessage());
}
Assim como no ByteArrayInputStream
, não é necessário fechar um ByteArrayOutputStream
, pois ele também opera exclusivamente em memória.
Resumo
ByteArrayInputStream
eByteArrayOutputStream
são streams que operam inteiramente sobre arrays de bytes em memória, sem acessar o sistema de arquivos.ByteArrayInputStream
lê dados de um array de bytes já existente.ByteArrayOutputStream
escreve dados para um buffer de bytes interno que cresce dinamicamente.- O método
toByteArray()
retorna uma cópia segura dos dados, protegendo o buffer interno. - O método
writeTo()
transfere eficientemente o conteúdo de umByteArrayOutputStream
para outro stream de saída. - Nenhuma das duas classes exige a chamada do método
close()
, pois não gerenciam recursos externos do sistema.