Java InputStream para Byte Array e ByteBuffer

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 ao StreamUtils da Spring

Conheça a classe StreamUtils da Spring.

Read more →

Introdução à serialização Java

Aprendemos como serializar e desserializar objetos em Java.

Read more →

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.

Read more →

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.