Автор оригинала: 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 .