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

Преобразуйте входной поток в строку в Java

В этом уроке мы рассмотрим, как преобразовать входной поток в строку Java множеством способов с практическими примерами.

Автор оригинала: David Landup.

Класс InputStream является классом высокого уровня, представляющим любой поток входных байтов в Java. Различные подклассы дополнительно определяют его использование, такие как BufferedInputStream , ByteArrayInputStream , SequenceInputStream и т.д.

Излишне говорить, что Входной поток может хранить любые данные, и в некоторых случаях они хранят содержимое строки в виде потока байтов.

В этом уроке мы рассмотрим как преобразовать входной поток в строку Java .

Давайте начнем с создания входного потока , который мы будем использовать во всех примерах. Они могут поступать из различных источников, но давайте сделаем один из строки , чтобы было легко проверить правильность вывода:

String string = "Input data, to be converted into an InputStream.";
InputStream inputStream = new ByteArrayInputStream(string.getBytes());

InputStream является абстрактным классом, и мы использовали один из его подклассов, ByteArrayInputStream для чтения байтов строки. Теперь у нас есть Входной поток , играющий роль фактического ввода, который мы можем легко проверить, сравнив с экземпляром string .

В Java есть множество классов для работы с потоками байтов, и здесь нет недостатка в вариантах и подходах. Мы сосредоточимся на некоторых из них:

  • Входной поток в строку с помощью InputStream.ReadAllBytes() – Лучший подход
  • Входной поток в строку с помощью ByteArrayOutputStream
  • Входной поток в строку с помощью InputStreamReader
  • Входной поток в строку с помощью BufferedReader.lines()
  • Входной поток в строку с помощью Apache Commons

Входной поток в строку с помощью InputStream.ReadAllBytes()

Начиная с Java 9, этот процесс был значительно упрощен |. InputStream очень часто создается как ByteArrayInputStream , прежде чем toByteArray() вызывается для извлечения из него байтов.

Этот процесс оптимизирован и заменен встроенным InputStream.ReadAllBytes() метод, который просто возвращает байты из InputStream – столь необходимый служебный метод.

Класс String принимает массив байт в свой конструктор, из которого формируется и возвращается Строка , что делает этот самый простой и наиболее читаемый подход для преобразования входного потока в Строку :

String result = new String(inputStream.readAllBytes());
System.out.println(result);

Это приводит к:

Input data, to be converted into an InputStream.

Примечание: Если Входной поток содержит более целого числа.MAX_VALUE байт, метод естественным образом выдает ошибку OutOfMemoryError .

Входной поток в строку с помощью ByteArrayOutputStream

Для версий, предшествующих Java 9, самый быстрый способ преобразования входного потока в строку заключается в использовании ByteArrayOutputStream .

Этот подход основан на том факте , что мы можем легко создавать строки из байтовых массивов , и на том факте, что ByteArrayOutputStream имеет очень удобный метод toString () .

Этот процесс практически является обратным тому, что мы делали в начале – построением входного потока | из строки:

// Instantiate an OutputStream that'll store the data from the InputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

// For each line of the InputStream, write it to the OutputStream, and move to the next
for (int data = inputStream.read(); data != -1; data = inputStream.read()) {
    byteArrayOutputStream.write(data);
}

// Convert byte array into String
// Optional: You can set a character set via `StandardCharsets` here
String result = byteArrayOutputStream.toString(StandardCharsets.UTF_8);
System.out.println(result);

Метод InputStream.read() считывает следующий байт в массиве, начиная с первого. Здесь мы сохраняем ссылку на первый байт как данные этой операции чтения, проверяем, является ли это -1 (достиг конца потока) и перейдите к следующему байту с помощью другой операции read () .

Выполнение этого кода приводит к:

Input data, to be converted into an InputStream.

Входной поток в строку с помощью InputStreamReader

Классы InputStream и OutputStream являются частью java.io пакет, который также включает в себя действительно удобный InputStreamReader класс, первоначально предназначенный как класс для чтения InputStream s.

InputStreamReader считывает байты из потока и декодирует их в символы, для которых вы также можете дополнительно указать с помощью перечисления Стандартные наборы символов :

// Read the InputStream into a Reader
Reader reader = new InputStreamReader(inputStream);

// Instantiate a StringBuilder to save the result
StringBuilder result = new StringBuilder();

// Read each byte and convert into a char, adding to the StringBuilder
for (int data = reader.read(); data != -1; data = reader.read()) {
    result.append((char)data);
}

// Convert StringBuilder to String
System.out.println(result.toString());

Это также приводит к:

Input data, to be converted into an InputStream.

Входной поток в строку с помощью BufferedReader

Вместо Reader вы также можете использовать BufferedReader ./| BufferedReader хранит большее количество байтов в буфере перед выполнением любых операций чтения/записи. Благодаря меньшему переключению контекста это более эффективный способ чтения и записи больших объемов данных, в то время как при меньших объемах разница незаметна.

В предыдущем примере мы могли бы вместо этого завернуть InputStreamReader в BufferedReader :

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

StringBuilder sb = new StringBuilder();

for (int data = reader.read(); data != -1; data = reader.read()) {
    sb.append((char)data);
}

System.out.println(sb.toString());

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Это приводит к тому же результату:

Input data, to be converted into an InputStream.

Примечание: Этот подход предпочтительнее предыдущего из-за повышенной эффективности, хотя он может быть незаметен для небольших объемов данных.

Входной поток в строку с помощью BufferedReader.lines()

В Java 8 класс BufferedReader получил новый метод lines () , который возвращает Поток из Строки s для каждой строки. Это делает легким чтение входного потока с помощью API потока:

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

String result = reader.lines().collect(Collectors.joining(System.lineSeparator()));

System.out.println(result);

Метод Collectors.joining() может работать без указания разделителя, однако это может привести к неожиданным результатам, когда входные данные содержат новые строки. Установив разделитель в System.LineSeparator() , мы позволяем механизму базовой системы включаться для концов строк.

Этот код приводит к:

Input data, to be converted into an InputStream.

Входной поток в строку с помощью Apache Commons

Наконец, давайте посмотрим, как этого добиться с помощью внешней библиотеки – Apache Commons, которая присутствует в значительном количестве проектов.

Чтобы использовать Apache Commons, нам придется добавить его зависимость в ваш собственный проект:


    commons-io
    commons-io

И с этим покончено, мы можем использовать его IOUtils класс:

String result = IOUtils.toString(inputStream);
System.out.println(result);

Метод также принимает необязательное перечисление StandardCharsets :

String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);

Выполнение этого кода приводит к:

Input data, to be converted into an InputStream.

Вывод

В этом уроке мы рассмотрели, как преобразовать Входной поток в строку в Java.

Мы рассмотрели новейший подход, прочитав все байты и построив строку напрямую, а также записав их в ByteArrayOutputStream , перед использованием Reader и BufferedReader и, наконец, завершив его использованием IOUtils Apache Commons .