Рубрики
Без рубрики

Java InputStream to Byte Array и ByteBuffer

Как преобразовать входной поток в байт[] с помощью простого Java, Guava или Commons IO.

Автор оригинала: Eugen Paraschiv.

1. Обзор

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

Эта статья является частью серии “Java – Back to Basic” здесь, на Baeldung.

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

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

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

Преобразования строк Java

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

Давайте рассмотрим получение массива байтов из простых входных потоков . Важным аспектом байтового массива является то, что он обеспечивает индексированный (быстрый) доступ к каждому 8-битному (байтовому) значению, хранящемуся в памяти . Следовательно, вы можете манипулировать этими байтами, чтобы контролировать каждый бит. Мы рассмотрим, как преобразовать простой входной поток в 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();
}

Начиная с Java 9, мы можем достичь того же самого с помощью специального метода на InputStream :

@Test
public void
  givenUsingPlainJava9_whenConvertingAnInputStreamToAByteArray_thenCorrect()
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 });

    byte[] data = is.readAllBytes();
}

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

Метод Долговые расписки.toByteArray() буферизует входные данные внутри системы, поэтому нет необходимости использовать BufferedInputStream instance при необходимости буферизации.

3. Преобразование в ByteBuffer

Теперь давайте рассмотрим получение ByteBuffer из InputStream. Это полезно, когда нам нужно выполнять быстрые и прямые низкоуровневые операции ввода-вывода в памяти .

Используя тот же подход, что и в предыдущих разделах, мы рассмотрим, как преобразовать 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. Конвертация С Использованием Гуавы

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

@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 , чтобы показать другой способ чтения всех байтов в 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 .