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

Java InputStream в строку

Как преобразовать входной поток в строку, используя обычную Java, Guava или Commons IO.

Автор оригинала: Eugen Paraschiv.

1. Обзор

В этом уроке мы рассмотрим , как преобразовать InputStream в строку , используя Guava , библиотеку Apache Commons IO и обычную Java.

Эта статья является частью серии “Java – Back to Basic” здесь, на Baeldung.

Дальнейшее чтение:

Java InputStream в массив байтов и ByteBuffer

Java – Запись входного потока в файл

Java – InputStream для чтения

2. Преобразование С Помощью Гуавы

Давайте начнем с примера Гуавы – использование функциональности ByteSource :

@Test
public void givenUsingGuava_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    ByteSource byteSource = new ByteSource() {
        @Override
        public InputStream openStream() throws IOException {
            return inputStream;
        }
    };

    String text = byteSource.asCharSource(Charsets.UTF_8).read();

    assertThat(text, equalTo(originalString));
}

Давайте пройдемся по ступенькам:

  • сначала – мы оборачиваем наш InputStream a ByteSource – и, насколько мне известно, это самый простой способ сделать это
  • затем – мы рассматриваем наш ByteSource как CharSource с кодировкой UTF8.
  • наконец – мы используем CharSource , чтобы прочитать его как строку.

более простой способ выполнить преобразование с помощью Guava , но поток должен быть явно закрыт; к счастью, мы можем просто использовать синтаксис try-with-resources, чтобы позаботиться об этом:

@Test
public void givenUsingGuavaAndJava7_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());
 
    String text = null;
    try (Reader reader = new InputStreamReader(inputStream)) {
        text = CharStreams.toString(reader);
    }
 
    assertThat(text, equalTo(originalString));
}

3. Преобразование С Помощью Apache Commons IO

Давайте теперь посмотрим, как это сделать с помощью библиотеки Commons IO.

Важным предостережением здесь является то, что – в отличие от Гуавы – ни один из этих примеров не закроет InputStream , поэтому я лично предпочитаю решение Гуавы.

@Test
public void givenUsingCommonsIo_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    String text = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name());
    assertThat(text, equalTo(originalString));
}

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

@Test
public void givenUsingCommonsIoWithCopy_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    StringWriter writer = new StringWriter();
    String encoding = StandardCharsets.UTF_8.name();
    IOUtils.copy(inputStream, writer, encoding);

    assertThat(writer.toString(), equalTo(originalString));
}

4. Преобразование С Помощью Java – InputStream

Давайте теперь рассмотрим подход более низкого уровня с использованием простой Java – an InputStream и простого StringBuilder :

@Test
public void givenUsingJava5_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(DEFAULT_SIZE);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    StringBuilder textBuilder = new StringBuilder();
    try (Reader reader = new BufferedReader(new InputStreamReader
      (inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) {
        int c = 0;
        while ((c = reader.read()) != -1) {
            textBuilder.append((char) c);
        }
    }
    assertEquals(textBuilder.toString(), originalString);
}

4.1. Использование Java 8

Java 8 приносит новый метод lines() в BufferedReader . Давайте посмотрим, как мы можем использовать его для преобразования InputStream в Строку:

@Test
public void givenUsingJava8_whenConvertingAnInputStreamToAString_thenCorrect() {
    String originalString = randomAlphabetic(DEFAULT_SIZE);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    String text = new BufferedReader(
      new InputStreamReader(inputStream, StandardCharsets.UTF_8)))
        .lines()
        .collect(Collectors.joining("\n"));

    assertThat(text, equalTo(originalString));
}

Важно отметить, что lines() использует метод readLine() под капотом. readLine() предполагает, что строка завершается любой подачей строки (“\n”), возвратом каретки (“\r”) или возвратом каретки, за которым немедленно следует подача строки. Другими словами, он поддерживает все распространенные стили End Of Line – Unix, Windows и даже старую Mac OS.

С другой стороны, когда мы используем Collectors.joining() , нам нужно явно решить, какой тип EOL мы хотим использовать для созданной Строки .

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

5. Преобразование с помощью Java и сканера

Далее – давайте рассмотрим простой пример Java – с использованием стандартного текста Scanner :

@Test
public void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    String text = null;
    try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) {
        text = scanner.useDelimiter("\\A").next();
    }

    assertThat(text, equalTo(originalString));
}

Обратите внимание, что InputStream будет закрыт при закрытии сканера .

Также стоит уточнить, что делает useDelimiter(“\\A”) . Здесь мы передали “\A”, которое является регулярным выражением маркера границы, обозначающим начало ввода. По сути, это означает, что вызов next() считывает весь входной поток.

Единственная причина, по которой это пример Java 7, а не Java 5, заключается в использовании оператора try-with-resources – превращение его в стандартный try-finally block будет отлично компилироваться с Java 5 .

6. Преобразование С Помощью ByteArrayOutputStream

Наконец, давайте рассмотрим еще один простой пример Java, на этот раз с использованием класса ByteArrayOutputStream :

@Test
public void givenUsingPlainJava_whenConvertingAnInputStreamToString_thenCorrect()
  throws IOException {
    String originalString = randomAlphabetic(8);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    int nRead;
    byte[] data = new byte[1024];
    while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, nRead);
    }

    buffer.flush();
    byte[] byteArray = buffer.toByteArray();
        
    String text = new String(byteArray, StandardCharsets.UTF_8);
    assertThat(text, equalTo(originalString));
}

В этом примере сначала InputStream преобразуется в ByteArrayOutputStream путем чтения и записи байтовых блоков, затем OutputStream преобразуется в массив байтов, который используется для создания Строки .

7. Преобразование С Помощью java.nio

Другое решение состоит в том, чтобы скопировать содержимое InputStream в файл, а затем преобразовать его в строку :

@Test
public void givenUsingTempFile_whenConvertingAnInputStreamToAString_thenCorrect() 
  throws IOException {
    String originalString = randomAlphabetic(DEFAULT_SIZE);
    InputStream inputStream = new ByteArrayInputStream(originalString.getBytes());

    Path tempFile = 
      Files.createTempDirectory("").resolve(UUID.randomUUID().toString() + ".tmp");
    Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING);
    String result = new String(Files.readAllBytes(tempFile));

    assertThat(result, equalTo(originalString));
}

Здесь мы используем файл java.nio.Files class для создания временного файла, а также копирования содержимого InputStream в файл. Затем тот же класс используется для преобразования содержимого файла в Строку с помощью метода ReadAllBytes () .

8. Заключение

После компиляции лучшего способа сделать простое преобразование – InputStream в строку – правильным и читаемым способом – и после просмотра стольких совершенно разных ответов и решений – я думаю, что для этого требуется четкая и краткая лучшая практика .

Реализацию всех этих примеров и фрагментов кода можно найти на GitHub – это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.