Pytanie Odczytaj / przekonwertuj parametr InputStream na ciąg
Jeśli masz java.io.InputStream
obiekt, jak powinieneś przetwarzać ten obiekt i tworzyć String
?
Załóżmy, że mam InputStream
zawiera dane tekstowe i chcę przekonwertować je na String
, więc na przykład mogę to zapisać w pliku dziennika.
Jaki jest najłatwiejszy sposób na zrobienie tego InputStream
i przekonwertuj go na String
?
public String convertStreamToString(InputStream is) {
// ???
}
3267
2017-11-21 16:47
pochodzenie
Odpowiedzi:
Dobrym sposobem na to jest użycie Apache commons IOUtils
skopiować InputStream
do a StringWriter
... coś jak
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();
lub nawet
// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding);
Ewentualnie możesz użyć ByteArrayOutputStream
jeśli nie chcesz mieszać swoich strumieni i pisarzy
2048
2017-11-21 16:54
Oto sposób korzystania tylko ze standardowej biblioteki Java (zauważ, że strumień nie jest zamknięty, YMMV).
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
Nauczyłem się tej sztuczki od "Głupie sztuczki ze skanera" artykuł. Powodem, dla którego to działa, jest ponieważ Skaner Iteruje nad żetonami w strumieniu, w tym przypadku oddzielamy tokeny za pomocą "początku granicy wejściowej" (\ A), co daje nam tylko jeden token dla całej zawartości strumienia.
Uwaga: jeśli potrzebujesz specyfiki kodowania strumienia wejściowego, możesz podać drugi argument Scanner
konstruktor, który wskazuje, jakiego zestawu znaków użyć (np. "UTF-8").
Końcówka kapelusza również trafia Jakub, który raz wskazał mi ten artykuł.
EDYTOWANE: Dzięki sugestii od Patrick, sprawił, że funkcja była bardziej niezawodna podczas obsługi pustego strumienia wejściowego. Jeszcze jedna edycja: nixed try / catch, sposób Patricka jest bardziej lakoniczny.
2093
2018-03-26 20:40
Podsumowując inne odpowiedzi znalazłem 11 głównych sposobów, aby to zrobić (patrz poniżej). Napisałem kilka testów wydajności (zobacz wyniki poniżej):
Sposoby konwersji obiektu InputStream na ciąg:
Za pomocą IOUtils.toString
(Apache Utils)
String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
Za pomocą CharStreams
(Guava)
String result = CharStreams.toString(new InputStreamReader(
inputStream, Charsets.UTF_8));
Za pomocą Scanner
(JDK)
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String result = s.hasNext() ? s.next() : "";
Za pomocą Stream API (Java 8). Ostrzeżenie: To rozwiązanie konwertuje różne podziały wierszy (np \r\n
) do \n
.
String result = new BufferedReader(new InputStreamReader(inputStream))
.lines().collect(Collectors.joining("\n"));
Za pomocą równoległy Stream API (Java 8). Ostrzeżenie: To rozwiązanie konwertuje różne podziały wierszy (np \r\n
) do \n
.
String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
.parallel().collect(Collectors.joining("\n"));
Za pomocą InputStreamReader
i StringBuilder
(JDK)
final int bufferSize = 1024;
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
Reader in = new InputStreamReader(inputStream, "UTF-8");
for (; ; ) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
return out.toString();
Za pomocą StringWriter
i IOUtils.copy
(Apache Commons)
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
return writer.toString();
Za pomocą ByteArrayOutputStream
i inputStream.read
(JDK)
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
// StandardCharsets.UTF_8.name() > JDK 7
return result.toString("UTF-8");
Za pomocą BufferedReader
(JDK). Ostrzeżenie: To rozwiązanie konwertuje różne podziały wierszy (np \n\r
) do line.separator
właściwość systemowa (na przykład w systemie Windows do "\ r \ n").
String newLine = System.getProperty("line.separator");
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder result = new StringBuilder();
String line; boolean flag = false;
while ((line = reader.readLine()) != null) {
result.append(flag? newLine: "").append(line);
flag = true;
}
return result.toString();
Za pomocą BufferedInputStream
i ByteArrayOutputStream
(JDK)
BufferedInputStream bis = new BufferedInputStream(inputStream);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while(result != -1) {
buf.write((byte) result);
result = bis.read();
}
// StandardCharsets.UTF_8.name() > JDK 7
return buf.toString("UTF-8");
Za pomocą inputStream.read()
i StringBuilder
(JDK). Ostrzeżenie: To rozwiązanie ma problemy z Unicode, na przykład z rosyjskim tekstem (działa poprawnie tylko z tekstem nieobsługującym kodu Unicode)
int ch;
StringBuilder sb = new StringBuilder();
while((ch = inputStream.read()) != -1)
sb.append((char)ch);
reset();
return sb.toString();
Ostrzeżenie:
Rozwiązania 4, 5 i 9 konwertują różne podziały wierszy na jeden.
Rozwiązanie 11 nie działa poprawnie z tekstem Unicode
Testy wydajności
Testy wydajności dla małych String
(długość = 175), adres URL w github (mode = średni czas, system = Linux, wynik 1 343 jest najlepszy):
Benchmark Mode Cnt Score Error Units
8. ByteArrayOutputStream and read (JDK) avgt 10 1,343 ± 0,028 us/op
6. InputStreamReader and StringBuilder (JDK) avgt 10 6,980 ± 0,404 us/op
10. BufferedInputStream, ByteArrayOutputStream avgt 10 7,437 ± 0,735 us/op
11. InputStream.read() and StringBuilder (JDK) avgt 10 8,977 ± 0,328 us/op
7. StringWriter and IOUtils.copy (Apache) avgt 10 10,613 ± 0,599 us/op
1. IOUtils.toString (Apache Utils) avgt 10 10,605 ± 0,527 us/op
3. Scanner (JDK) avgt 10 12,083 ± 0,293 us/op
2. CharStreams (guava) avgt 10 12,999 ± 0,514 us/op
4. Stream Api (Java 8) avgt 10 15,811 ± 0,605 us/op
9. BufferedReader (JDK) avgt 10 16,038 ± 0,711 us/op
5. parallel Stream Api (Java 8) avgt 10 21,544 ± 0,583 us/op
Testy wydajności dla dużych String
(długość = 50100), adres URL w github (mode = średni czas, system = Linux, wynik 200 715 jest najlepszy):
Benchmark Mode Cnt Score Error Units
8. ByteArrayOutputStream and read (JDK) avgt 10 200,715 ± 18,103 us/op
1. IOUtils.toString (Apache Utils) avgt 10 300,019 ± 8,751 us/op
6. InputStreamReader and StringBuilder (JDK) avgt 10 347,616 ± 130,348 us/op
7. StringWriter and IOUtils.copy (Apache) avgt 10 352,791 ± 105,337 us/op
2. CharStreams (guava) avgt 10 420,137 ± 59,877 us/op
9. BufferedReader (JDK) avgt 10 632,028 ± 17,002 us/op
5. parallel Stream Api (Java 8) avgt 10 662,999 ± 46,199 us/op
4. Stream Api (Java 8) avgt 10 701,269 ± 82,296 us/op
10. BufferedInputStream, ByteArrayOutputStream avgt 10 740,837 ± 5,613 us/op
3. Scanner (JDK) avgt 10 751,417 ± 62,026 us/op
11. InputStream.read() and StringBuilder (JDK) avgt 10 2919,350 ± 1101,942 us/op
Wykresy (testy wydajności w zależności od długości strumienia wejściowego w systemie Windows 7)

Test wydajności (średni czas) w zależności od długości strumienia wejściowego w systemie Windows 7:
length 182 546 1092 3276 9828 29484 58968
test8 0.38 0.938 1.868 4.448 13.412 36.459 72.708
test4 2.362 3.609 5.573 12.769 40.74 81.415 159.864
test5 3.881 5.075 6.904 14.123 50.258 129.937 166.162
test9 2.237 3.493 5.422 11.977 45.98 89.336 177.39
test6 1.261 2.12 4.38 10.698 31.821 86.106 186.636
test7 1.601 2.391 3.646 8.367 38.196 110.221 211.016
test1 1.529 2.381 3.527 8.411 40.551 105.16 212.573
test3 3.035 3.934 8.606 20.858 61.571 118.744 235.428
test2 3.136 6.238 10.508 33.48 43.532 118.044 239.481
test10 1.593 4.736 7.527 20.557 59.856 162.907 323.147
test11 3.913 11.506 23.26 68.644 207.591 600.444 1211.545
1656
2018-02-17 00:58
Apache Commons pozwala:
String myString = IOUtils.toString(myInputStream, "UTF-8");
Oczywiście możesz wybrać inne kodowanie znaków oprócz UTF-8.
Zobacz także: (Dokumenty)
794
2017-12-08 20:13
Biorąc pod uwagę plik należy najpierw uzyskać java.io.Reader
instancja. To można następnie odczytać i dodać do StringBuilder
(nie potrzebujemy StringBuffer
jeśli nie uzyskujemy dostępu do niego w wielu wątkach, i StringBuilder
jest szybszy). Sztuczka polega na tym, że pracujemy w blokach i jako takie nie potrzebujemy innych strumieni buforujących. Rozmiar bloku jest sparametryzowany w celu optymalizacji wydajności w czasie wykonywania.
public static String slurp(final InputStream is, final int bufferSize) {
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
try (Reader in = new InputStreamReader(is, "UTF-8")) {
for (;;) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
}
catch (UnsupportedEncodingException ex) {
/* ... */
}
catch (IOException ex) {
/* ... */
}
return out.toString();
}
263
2017-08-04 08:29
Co powiesz na to?
InputStream in = / * Twój InputStream * /;
StringBuilder sb=new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String read;
while((read=br.readLine()) != null) {
//System.out.println(read);
sb.append(read);
}
br.close();
return sb.toString();
226
2017-07-13 15:56
Jeśli korzystasz z Kolekcji Google / Guava, możesz wykonać następujące czynności:
InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);
Zauważ, że drugi parametr (tj. Charsets.UTF_8) dla InputStreamReader
nie jest konieczne, ale ogólnie dobrym pomysłem jest określenie kodowania, jeśli je znasz (co powinieneś!)
153
2018-05-08 20:24
To jest moje czyste rozwiązanie Java i Android, działa dobrze ...
public String readFullyAsString(InputStream inputStream, String encoding)
throws IOException {
return readFully(inputStream).toString(encoding);
}
public byte[] readFullyAsBytes(InputStream inputStream)
throws IOException {
return readFully(inputStream).toByteArray();
}
private ByteArrayOutputStream readFully(InputStream inputStream)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos;
}
107
2018-06-10 21:07
Co powiesz na:
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
public static String readInputStreamAsString(InputStream in)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while(result != -1) {
byte b = (byte)result;
buf.write(b);
result = bis.read();
}
return buf.toString();
}
56
2018-01-01 03:43
Oto najbardziej eleganckie, czysto Java (bez biblioteki) rozwiązanie, które wymyśliłem po kilku eksperymentach:
public static String fromStream(InputStream in) throws IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
return out.toString();
}
55
2017-09-02 11:50