Java InputStream para Byte Array e ByteBuffer
1. Visão geral
Neste tutorial rápido, vamos dar uma olhada em como converter umInputStream embyte[]eByteBuffer - primeiro usando Java puro, depois usando Guava e Commons IO.
Este artigo faz parte dethe “Java – Back to Basic” series aqui no exemplo.
Leitura adicional:
Introdução à serialização Java
Aprendemos como serializar e desserializar objetos em Java.
Conversões de seqüência de caracteres Java
Exemplos rápidos e práticos focados na conversão de objetos String em diferentes tipos de dados em Java.
2. Converter para matriz de bytes
Vejamos como obter uma matriz de bytes de fluxos de entrada simples. O aspecto importante de uma matriz de bytes é queit enables an indexed (fast) access to each 8-bit (a byte) value stored in memory. Portanto, você pode manipular esses bytes para controlar cada bit. Vamos dar uma olhada em como converter um fluxo de entrada simples embyte[] - primeiro usando Java puro, depois usandoGuavaeApache Commons IO.
2.1. Converter usando Java simples
Vamos começar com uma solução Java focada em lidar com um fluxo de tamanho fixo:
@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);
}
No caso de um fluxo em buffer - onde estamos lidando com um fluxo em buffer e não sabemos o tamanho exato dos dados subjacentes, precisamos tornar a implementação mais flexível:
@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();
}
2.2. Converter usando Guava
Vejamos agora a solução simples baseada em Guava - usando a conveniente classe de utilitário 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. Converter usando Commons IO
E finalmente - uma solução direta usando o 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);
}
O métodoIOUtils.toByteArray() armazena a entrada internamente, portanto, háno need to use a BufferedInputStream instance quando o buffer é necessário.
3. Converter paraByteBuffer
Agora, vamos ver como obterByteBuffer de umInputStream. Isso éuseful whenever we need to do fast and direct low-level I/O operations in memory.
Usando a mesma abordagem das seções acima, vamos dar uma olhada em como converter umInputStream emByteBuffer - primeiro usando Java puro, depois usando Guava e Commons IO.
3.1. Converter usando Java simples
No caso de um fluxo de bytes - sabemos o tamanho exato dos dados subjacentes. Vamos usar o métodoByteArrayInputStream#available para ler o fluxo de bytes em umByteBuffer:
@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. Converter usando Guava
Vejamos agora uma solução simples baseada em Guava - usando a conveniente classe de utilitárioByteStreams:
@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);
}
Aqui usamos um loop while com o métodohasRemaining para mostrar uma maneira diferente de ler todos os bytes emByteBuffer.. Caso contrário, a asserção falhará porque a posição do índiceByteBuffer será zero.
3.3. Converter usando Commons IO
E, finalmente - usando Apache Commons IO e a classeIOUtils:
@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. Conclusão
Este artigo ilustrou várias maneiras de converter um fluxo de entrada bruto em uma matriz de bytes e umByteBuffer usando Java simples, Guava e Apache Commons IO.
A implementação de todos esses exemplos pode ser encontrada em nossoGitHub project.