Java InputStream към низ

1. Общ преглед

В този урок ще разгледаме как да конвертираме InputStream в String , използвайки Guava, библиотеката на Apache Commons IO и обикновената Java.

Тази статия е част от поредицата „Java - Back to Basic“ тук на Baeldung.

2. Преобразуване с гуава

Нека започнем с пример с Guava - използвайки функционалността 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 с 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.

Важна забележка тук е, че - за разлика от Guava - нито един от тези примери няма да затвори InputStream - поради което аз лично предпочитам решението Guava.

@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 - 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 носи нов метод на редове () в 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)); }

Важно е да споменем, че линиите () използват метода readLine () под капака. readLine () приема, че редът е прекратен от някое от подаване на линия („\ n“), връщане на каретка („\ r“) или връщане на карета, последвано веднага от подаване на линия. С други думи, той поддържа всички често срещани стилове End Of Line - Unix, Windows и дори стари Mac OS.

От друга страна, когато използваме Collectors.joining () , трябва изрично да решим кой тип EOL искаме да използваме за създадения String .

Можем да използваме и Collectors.joining (System.lineSeparator ()) , като в този случай изходът зависи от системните настройки.

5. Конвертиране с Java и скенер

След това - нека разгледаме обикновен пример за Java - използвайки стандартен текстов скенер :

@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', което е граничен маркер, обозначаващ началото на входа. По същество това означава, че следващото () повикване чете целия входен поток.

Единствената причина това е пример за Java 7, а не за Java 5, е използването на инструкцията try-with-resources - превръщането на това в стандартен блок try- final ще се компилира добре с 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.file.Files, за да създадем временен файл, както и да копираме съдържанието на InputStream във файла. След това, същият клас се използва за преобразуване на съдържанието на файла в String с метода readAllBytes () .

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

След като съставих най-добрия начин да направя простото преобразуване - InputStream към String - по правилен и четим начин - и след като видях толкова много различни отговори и решения - мисля, че се изисква ясна и кратка най-добра практика за това .

Внедряването на всички тези примери и кодови фрагменти може да бъде намерено в GitHub - това е проект, базиран на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.