Java InputStream в байтовый массив

Java InputStream для байтового массива и ByteBuffer

1. обзор

В этом кратком руководстве мы рассмотрим, как преобразоватьInputStream вbyte[] иByteBuffer - сначала с использованием простой Java, затем с помощью Guava и Commons IO.

Эта статья является частьюthe “Java – Back to Basic” series здесь для примера.

Дальнейшее чтение:

Введение в Spring's StreamUtils

Откройте для себя класс Spring StreamUtils.

Read more

Введение в сериализацию Java

Мы узнаем, как сериализовать и десериализовать объекты в Java.

Read more

Строковые преобразования Java

Быстрые и практические примеры, посвященные преобразованию объектов String в различные типы данных в Java.

Read more

2. Преобразовать в байтовый массив

Давайте посмотрим на получение байтового массива из простых входных потоков. Важным аспектом байтового массива является то, чтоit enables an indexed (fast) access to each 8-bit (a byte) value stored in memory. Следовательно, вы можете манипулировать этими байтами для управления каждым битом. Мы собираемся взглянуть на то, как преобразовать простой входной поток вbyte[] - сначала с использованием простой Java, затем с помощьюGuava иApache Commons IO.

2.1. Преобразование с использованием простой Java

Начнем с решения Java, ориентированного на работу с потоком фиксированного размера:

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

В случае с буферизованным потоком, когда мы имеем дело с буферизованным потоком и не знаем точного размера базовых данных, нам нужно сделать реализацию более гибкой:

@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. Преобразование с использованием гуавы

Давайте теперь посмотрим на простое решение на основе Guava - с помощью удобного служебного класса 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. Преобразование с использованием Commons IO

И, наконец, простое решение с использованием 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);
}

МетодIOUtils.toByteArray() выполняет внутреннюю буферизацию ввода, поэтому существуетno need to use a BufferedInputStream instance, когда требуется буферизация.

3. Преобразовать вByteBuffer

Теперь давайте посмотрим, как получитьByteBuffer изInputStream.. Этоuseful whenever we need to do fast and direct low-level I/O operations in memory.

Используя тот же подход, что и в предыдущих разделах, мы рассмотрим, как преобразоватьInputStream вByteBuffer - сначала с использованием простой Java, а затем с помощью Guava и Commons IO.

3.1. Преобразование с использованием простой Java

В случае байтового потока - мы знаем точный размер базовых данных. Давайте воспользуемся методомByteArrayInputStream#available  для чтения байтового потока вByteBuffer:

@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. Преобразование с использованием гуавы

Давайте теперь посмотрим на простое решение на основе Guava - используя удобный служебный классByteStreams:

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

Здесь мы используем цикл while с методомhasRemaining to, показывающий другой способ чтения всех байтов вByteBuffer.. В противном случае утверждение не будет выполнено, потому что позиция индексаByteBuffer будет равна нулю.

3.3. Преобразование с использованием Commons IO

И наконец - с помощью Apache Commons IO и классаIOUtils:

@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. Заключение

В этой статье проиллюстрированы различные способы преобразования необработанного входного потока в байтовый массив иByteBuffer с использованием простых Java, Guava и Apache Commons IO.

Реализацию всех этих примеров можно найти в нашемGitHub project.