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.