Progress28.ru

IT Новости
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java byte array to inputstream

Convert InputStream to byte array in Java

How do I read an entire InputStream into a byte array?

31 Answers 31

You can use Apache Commons IO to handle this and similar tasks.

The IOUtils type has a static method to read an InputStream and return a byte[] .

Internally this creates a ByteArrayOutputStream and copies the bytes to the output, then calls toByteArray() . It handles large files by copying the bytes in blocks of 4KiB.

You need to read each byte from your InputStream and write it to a ByteArrayOutputStream . You can then retrieve the underlying byte array by calling toByteArray() ; e.g.

Finally, after twenty years, there’s a simple solution without the need for a 3rd party library, thanks to Java 9:

Note also the convenience methods readNBytes(byte[] b, int off, int len) and transferTo(OutputStream) addressing recurring needs.

Use vanilla Java’s DataInputStream and its readFully Method (exists since at least Java 1.4):

There are some other flavors of this method, but I use this all the time for this use case.

If you happen to use google guava, it’ll be as simple as :

As always, also Spring framework (spring-core since 3.2.2) has something for you: StreamUtils.copyToByteArray()

Safe solution (with capability of close streams correctly):

Kotlin version (when Java 9+ isn’t accessible):

To avoid nested use see here.

Do you really need the image as a byte[] ? What exactly do you expect in the byte[] — the complete content of an image file, encoded in whatever format the image file is in, or RGB pixel values?

Other answers here show you how to read a file into a byte[] . Your byte[] will contain the exact contents of the file, and you’d need to decode that to do anything with the image data.

Java’s standard API for reading (and writing) images is the ImageIO API, which you can find in the package javax.imageio . You can read in an image from a file with just a single line of code:

This will give you a BufferedImage , not a byte[] . To get at the image data, you can call getRaster() on the BufferedImage . This will give you a Raster object, which has methods to access the pixel data (it has several getPixel() / getPixels() methods).

Lookup the API documentation for javax.imageio.ImageIO , java.awt.image.BufferedImage , java.awt.image.Raster etc.

ImageIO supports a number of image formats by default: JPEG, PNG, BMP, WBMP and GIF. It’s possible to add support for more formats (you’d need a plug-in that implements the ImageIO service provider interface).

See also the following tutorial: Working with Images

Шпаргалка Java программиста 7.1 Типовые задачи: Оптимальный путь преобразования InputStream в строку

У меня есть хобби: я собираю различные решения типовых задач в Java, которые нахожу в инете, и пытаюсь выбрать наиболее оптимальное по размеру/производительности/элегантности. В первую очередь по производительности. Давайте рассмотрим такую типовую задач, которые часто встречаются в программировании на Java как «преобразование InputStream в строку» и разные варианты её решения.

Посмотрим какие ограничения есть у каждого (требования подключения определенной библиотеки/определенной версии, корректная работа с unicode и т.д.). Английскую версию этой статьи можно найти в моем ответе на stackoverflow. Тесты в моем проекте на github.

Преобразование InputStream в строку (String)

Очень часто встречающая задача, давайте рассмотрим какими способами можно это сделать (их будет 11):

Используя IOUtils.toString из библиотеки Apache Commons . Один из самых коротких однострочников.

Читать еще:  Java api documentation на русском

Используя CharStreams из библиотеки guava . Тоже довольно короткий код.

Используя Scanner (JDK). Решение короткое, хитрое, с помощью чистого JDK, но это скорее хак, который вынесет мозг тем кто о таком фокусе не знает.

Используя Stream Api с помощью Java 8 . Предупреждение: Оно заменяет разные переносы строки (такие как rn ) на n , иногда это может быть критично.

Используя parallel Stream Api ( Java 8 ). Предупреждение: Как и 4 решение, оно заменяет разные переносы строки (такие как rn ) на n .

Используя InputStreamReader и StringBuilder из обычного JDK

Используя StringWriter и IOUtils.copy из Apache Commons

Используя ByteArrayOutputStream и inputStream.read из JDK

Используя BufferedReader из JDK . Предупреждение: Это решение заменяет разные переносы строк (такие как nr ) на line.separator system property (например, в Windows на «rn»).

Используя BufferedInputStream и ByteArrayOutputStream из JDK

Используя inputStream.read() и StringBuilder ( JDK ). Предупреждение: Это решение не работает с Unicode, например с русским текстом

Итак о использовании:

Решения 4 , 5 и 9 преобразую разные переносы строки в одну.

Решения 11 не работает с Unicode текстом

  • Решение 1 , 7 требует использование библиотеки Apache Commons, 2 требует библиотеку Guava, 4 и 5 требуют Java 8 и выше,
  • Замеры производительности

    Предупреждение: замеры производительности всегда сильно зависят от системы, условий замера и т.п. Я измерял на двух разных компьютерах, один Windows 8.1, Intel i7-4790 CPU 3.60GHz2, 16Gb, второй — Linux Mint 17.2, Celeron Dual-Core T3500 2.10Ghz2, 6Gb, однако не могу гарантировать что результаты являются абсолютной истиной, вы всегда можете повторить тесты (test1 и test2) на вашей системе.

    Замеры производительности для небольших строк (длина = 175), тесты можно найти на github (режим = среднее время выполнения (AverageTime), система = Linux Mint 17.2, Celeron Dual-Core T3500 2.10Ghz*2, 6Gb, чем значение ниже тем лучше, 1,343 — наилучшее):

    Замеры производительности для больших строк (длина = 50100), тесты можно найти на github (режим = среднее время выполнения (AverageTime), система = Linux Mint 17.2, Celeron Dual-Core T3500 2.10Ghz*2, 6Gb, чем значение ниже тем лучше, 200,715 — наилучшее):

    График зависимости среднего времени от длины строки, система Windows 8.1, Intel i7-4790 CPU 3.60GHz 3.60GHz, 16Gb:

    Таблица зависимости среднего времени от длины строки, система Windows 8.1, Intel i7-4790 CPU 3.60GHz 3.60GHz, 16Gb:

    Выводы

    Самым быстрым решением во всех случаях и всех системах оказался 8 тест: Используя ByteArrayOutputStream и inputStream.read из JDK

    Коротким и весьма быстрым решением будет использование IOUtils.toString из Apache Commons

    Stream Api из Java 8 показывает среднее время, а использование параллельных стримов имеет смысл только при довольно большой строки, иначе он работает очень долго (что в общем-то было ожидаемо)

  • Решение 11 лучше не использовать в принципе, так как он работает медленнее всех и не работает с Unicode,
  • Конвертировать InputStream, чтобы байтовый массив в Java

    Как я могу прочитать всю InputStream в массив байтов?

    30 ответов:

    вы можете использовать Apache Commons IO для решения этой и подобных задач.

    The IOUtils тип имеет статический метод, чтобы прочитать InputStream и вернуть a byte[] .

    внутренне это создает ByteArrayOutputStream и копирует байты на выход, а затем вызывает toByteArray() . Он обрабатывает большие файлы, копируя байты в блоках 4KiB.

    вам нужно прочитать каждый байт из вашего InputStream и запишите его в ByteArrayOutputStream . Затем вы можете получить базовый массив байтов, вызвав toByteArray() , например,

    наконец, после двадцати лет, есть простое решение без необходимости в сторонней библиотеке, благодаря Java 9:

    обратите внимание также на методы удобства readNBytes(byte[] b, int off, int len) и transferTo(OutputStream) устранение повторяющихся потребностей.

    Если вы используете google guava, это будет так :

    Читать еще:  Восстановление системы windows 7 через безопасный режим

    используйте ваниль Java DataInputStream и readFully метод (существует, по крайней мере, с Java 1.4):

    есть несколько других разновидностей этого метода, но я использую это все время для этого случая использования.

    Как всегда, кроме Spring framework (spring-core с 3.2.2) есть что-то для вас: StreamUtils.copyToByteArray()

    вам действительно нужно изображение как byte[] ? Что именно вы ожидаете в byte[] — полное содержимое файла изображения, закодированное в любом формате, в котором находится файл изображения, или значения пикселей RGB?

    другие ответы здесь показать вам, как читать файл в byte[] . Ваш byte[] будет содержать точное содержимое файла, и вам нужно будет декодировать это, чтобы сделать что-нибудь с данными изображения.

    стандартный API Java для чтения (и записи) изображений является ImageIO API, который вы можете найти в пакете javax.imageio . Вы можете прочитать изображение из файла только с одной строкой кода:

    это даст вам BufferedImage , а не byte[] . Чтобы получить данные изображения, вы можете позвонить getRaster() на BufferedImage . Это даст вам Raster объект, который имеет методы для доступа к данным пикселей (он имеет несколько getPixel() / getPixels() методов).

    поиск документации API для javax.imageio.ImageIO , java.awt.image.BufferedImage , java.awt.image.Raster так далее.

    ImageIO поддерживает ряд форматов изображений по умолчанию: JPEG, PNG, BMP, WBMP и GIF. Можно добавить поддержку для большего количества форматов (вам понадобится плагин, который реализует интерфейс поставщика услуг ImageIO).

    см. также следующий учебник:работа с изображениями

    Если вы не хотите использовать библиотеку Apache commons-io, этот фрагмент взят из sun.разное.IOUtils class. Это почти в два раза быстрее, чем обычная реализация с помощью ByteBuffers:

    в случае, если кто-то все еще ищет решение без зависимости и если у вас есть файл.

    @Adamski: вы можете полностью избежать буфера.

    Класс InputStream

    Базовый класс InputStream представляет классы, которые получают данные из различных источников:

    • массив байтов
    • строка (String)
    • файл
    • канал (pipe): данные помещаются с одного конца и извлекаются с другого
    • последовательность различных потоков, которые можно объединить в одном потоке
    • другие источники (например, подключение к интернету)

    Для работы с указанными источниками используются подклассы базового класса InputStream:

    BufferedInputStream Буферизированный входной поток ByteArrayInputStream Позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока. DataInputStream Входной поток, включающий методы для чтения стандартных типов данных Java FileInputStream Для чтения информации из файла FilterInputStream Абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства. InputStream Абстрактный класс, описывающий поток ввода ObjectInputStream Входной поток для объектов StringBufferInputStream Превращает строку (String) во входной поток данных InputStream PipedInputStream Реализует понятие входного канала. PushbackInputStream Входной поток, поддерживающий однобайтовый возврат во входной поток SequenceInputStream Сливает два или более потока InputStream в единый поток

    • int available() — возвращает количество байтов ввода, доступные в данный момент для чтения
    • close() — закрывает источник ввода. Следующие попытки чтения передадут исключение IOException
    • void mark(int readlimit) — помещает метку в текущую точку входного потока, которая остаётся корректной до тех пор, пока не будет прочитано readlimint байт
    • boolean markSupported() — возвращает true, если методы mark() и reset() поддерживаются потоком
    • int read() — возвращает целочисленное представление следующего доступного байта в потоке. При достижении конца файла возвращается значение -1
    • int read(byte[] buffer) — пытается читать байты в буфер, возвращая количество прочитанных байтов. По достижении конца файла возвращает значение -1
    • int read(byte[] buffer, int byteOffset, int byteCount) — пытается читать до byteCount байт в buffer, начиная с смещения byteOffset. По достижении конца файла возвращает -1
    • reset() — сбрасывает входной указатель в ранее установленную метку
    • long skip(long byteCount) — пропускает byteCount байт ввода, возвращая количество проигнорированных байтов
    Читать еще:  Видеодрайвер перестал отвечать и был успешно восстановлен

    Как преобразовать InputStream в строку

    1. Using IOUtils.toString (Apache Utils):
    2. Using CharStreams (guava)
    3. Using Scanner (JDK)
      символ «А» является символом начала текста, таким образом вызов next() вернет сразу всю строку.
    4. Using Stream Api (Java 8). Warning: This solution convert different linebreaks (like rn) to n.
    5. Using parallel Stream Api (Java 8). Warning: This solution convert different linebreaks (like rn) to n.
    6. Using InputStreamReader and StringBuilder (JDK)
    7. Using StringWriter and IOUtils.copy (Apache Commons)
    8. Using ByteArrayOutputStream and inputStream.read (JDK)
    9. Using BufferedReader (JDK). Warning: This solution convert different linebreaks (like nr) to line.separator system property (for example, in Windows to «rn»).
    10. Using BufferedInputStream and ByteArrayOutputStream (JDK)
    11. Using inputStream.read() and StringBuilder (JDK). Warning: This soulition has problem with Unicode, for example with Russian text (work correctly only with non-Unicode text)

    Warning:
    Solutions 4, 5 and 9 convert different linebreaks to one.
    Soulution 11 can’t work correclty with Unicode text

    BufferedInputStream

    Буферизация ввода-вывода является удобным способом оптимизации производительности, позволяя заключить в оболочку любой поток класса InputStream.

    У класса есть конструктор, где размер буфера устанавливается по умолчанию. Также можно использовать конструктор, где размер буфера устанавливается вручную. Рекомендуется использовать размеры буфера, кратные размеру страницы памяти, дисковому блоку и т.п. и может зависеть от принимающей операционной системы, объёма доступной памяти и конфигурации машины.

    ByteArrayInputStream

    Класс ByteArrayInputStream использует байтовый массив в качестве источника данных. У данного класса можно не вызывать метод close().

    DataInputStream — Форматированное чтение из памяти

    Для чтения байтовых данных (не строк) применяется класс DataInputStream. В этом случае необходимо использовать классы из группы InputStream.

    Для преобразования строки в массив байтов, пригодный для помещения в поток ByteArrayInputStream, в классе String предусмотрен метод getBytes(). Полученный ByteArrayInputStream представляет собой поток InputStream, подходящий для передачи DataInputStream.

    При побайтовом чтении символов из форматированного потока DataInputStream методом readByte() любое полученное значение будет считаться действительным, поэтому возвращаемое значение неприменимо для идентификации конца потока. Вместо этого можно использовать метод available(), который сообщает, сколько еще осталось символов.

    Класс DataInputStream позволяет читать элементарные данные из потока через интерфейс DataInput, который определяет методы, преобразующие элементарные значения в форму последовательности байтов. Такие потоки облегчают сохранение в файле двоичных данных.

    FileInputStream

    Класс FileInputStream создаёт объект класса InputStream, который можно использовать для чтения байтов из файла.

    • FileInputStream (File file) — указывается объекта типа File
    • FileInputStream (FileDescriptor fd)
    • FileInputStream (String path) — указывается полное имя файла

    При создании объект открывается для чтения. Класс переопределяет методы класса InputStream, кроме методов mark() и reset().

    Для чтения байтов входного потока из файла используется конструкция:

    PushbackInputStream

    Разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток. Класс PushbackInputStream представляет механизм «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий раз, не извлекая информации.

    У класса есть дополнительный метод unread().

    SequenceInputStream

    Класс SequenceInputStream позволяет соединять вместе несколько экземпляров класса InputStream. Конструктор принимает в качестве аргумента либо пару объектов класса InputStream, либо интерфейс Enumeration.

    Во время работы класс выполняет запросы на чтение из первого объекта класса InputStream и до конца, а затем переключается на второй. При использовании интерфейса работа продолжится по всем объектам класса InputStream. По достижении конца каждого файла, связанный с ним поток закрывается. Закрытие потока, созданного объектом класса SequenceInputStream, приводит к закрытию всех открытых потоков.

    Ссылка на основную публикацию
    Adblock
    detector