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