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

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

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

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

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

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

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

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

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

InputStream в String с InputStream.readAllBytes ()

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

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

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

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

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

 Input data, to be converted into an InputStream. 

Примечание. Если InputStream содержит больше Integer.MAX_VALUE , метод естественным образом вызывает OutOfMemoryError .

InputStream в String с ByteArrayOutputStream

Для версий до Java 9 самый быстрый способ преобразовать InputStream в String - использовать ByteArrayOutputStream .

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

Этот процесс практически противоположен тому, что мы делали в начале - построению InputStream из String:

 // 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() считывает следующий байт в массиве, начиная с первого. Здесь мы сохраняем ссылку на первый байт как data этой операции чтения, проверяем, -1 (дошел до конца потока) и переходим к следующему байту с помощью другой операции read()

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

 Input data, to be converted into an InputStream. 

InputStream в String с InputStreamReader

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

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

 // 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. 

InputStream в String с 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()); 

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

 Input data, to be converted into an InputStream. 

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

InputStream в String с помощью BufferedReader.lines ()

В Java 8 класс BufferedReader lines() , который возвращает Stream of String для каждой строки. Это делает его легким , чтобы прочитать InputStream , используя 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. 

InputStream в String с помощью Apache Commons

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

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

 <dependency> 
 <groupId>commons-io</groupId> 
 <artifactId>commons-io</artifactId> 
 </dependency> 

И после этого мы можем использовать его класс 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. 

Заключение

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

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

comments powered by Disqus