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, така че трябва да е лесно да се импортира и да се изпълнява както е.