4724 Stimmen

Wie lese/konvertiere ich einen InputStream in einen String in Java?

Wenn Sie eine java.io.InputStream Objekt, wie sollten Sie dieses Objekt verarbeiten und eine String ?


Angenommen, ich habe eine InputStream die Textdaten enthält, und ich möchte sie in eine String so dass ich das zum Beispiel in eine Protokolldatei schreiben kann.

Wie kann man am einfachsten die InputStream und konvertieren sie in eine String ?

public String convertStreamToString(InputStream is) {
    // ???
}

0 Stimmen

2 Stimmen

Denken Sie daran, dass Sie die Kodierung des Eingangsstroms berücksichtigen müssen. Die Systemvorgabe ist nicht unbedingt immer die, die Sie wollen.

23 Stimmen

Die meisten dieser Antworten wurden vor Java 9 geschrieben, aber jetzt kann man mit .readAllBytes ein Byte-Array aus dem InputStream holen. Also, einfach "new String(inputStream.readAllBytes())" funktioniert mit dem byte[] Konstruktor von String.

3522voto

Slava Vedenin Punkte 54320

Fassen Sie andere Antworten zusammen. Ich habe 11 Hauptwege gefunden, dies zu tun (siehe unten). Und ich habe einige Leistungstests geschrieben (siehe Ergebnisse unten):

Wege zur Umwandlung eines InputStreams in einen String:

  1. Verwendung von IOUtils.toString (Apache Utils)

     String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
  2. Verwendung von CharStreams (Guave)

     String result = CharStreams.toString(new InputStreamReader(
           inputStream, Charsets.UTF_8));
  3. Verwendung von Scanner (JDK)

     Scanner s = new Scanner(inputStream).useDelimiter("\\A");
     String result = s.hasNext() ? s.next() : "";
  4. Verwendung von Stream-API (Java 8). Warnung : Diese Lösung konvertiert verschiedene Zeilenumbrüche (wie \r\n ) an \n .

     String result = new BufferedReader(new InputStreamReader(inputStream))
       .lines().collect(Collectors.joining("\n"));
  5. Verwendung von parallele Stream-API (Java 8). Warnung : Diese Lösung konvertiert verschiedene Zeilenumbrüche (wie \r\n ) an \n .

     String result = new BufferedReader(new InputStreamReader(inputStream))
        .lines().parallel().collect(Collectors.joining("\n"));
  6. Verwendung von InputStreamReader y StringBuilder (JDK)

     int bufferSize = 1024;
     char[] buffer = new char[bufferSize];
     StringBuilder out = new StringBuilder();
     Reader in = new InputStreamReader(stream, StandardCharsets.UTF_8);
     for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
         out.append(buffer, 0, numRead);
     }
     return out.toString();
  7. Verwendung von StringWriter y IOUtils.copy (Apache Commons)

     StringWriter writer = new StringWriter();
     IOUtils.copy(inputStream, writer, "UTF-8");
     return writer.toString();
  8. Verwendung von ByteArrayOutputStream y inputStream.read (JDK)

     ByteArrayOutputStream result = new ByteArrayOutputStream();
     byte[] buffer = new byte[1024];
     for (int length; (length = inputStream.read(buffer)) != -1; ) {
         result.write(buffer, 0, length);
     }
     // StandardCharsets.UTF_8.name() > JDK 7
     return result.toString("UTF-8");
  9. Verwendung von BufferedReader (JDK). Warnung: Diese Lösung konvertiert verschiedene Zeilenumbrüche (wie \n\r ) an line.separator Systemeigenschaft (z. B. in Windows auf " \r\n ").

     String newLine = System.getProperty("line.separator");
     BufferedReader reader = new BufferedReader(
             new InputStreamReader(inputStream));
     StringBuilder result = new StringBuilder();
     for (String line; (line = reader.readLine()) != null; ) {
         if (result.length() > 0) {
             result.append(newLine);
         }
         result.append(line);
     }
     return result.toString();
  10. Verwendung von BufferedInputStream y ByteArrayOutputStream (JDK)

    BufferedInputStream bis = new BufferedInputStream(inputStream);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    for (int result = bis.read(); result != -1; result = bis.read()) {
        buf.write((byte) result);
    }
    // StandardCharsets.UTF_8.name() > JDK 7
    return buf.toString("UTF-8");
  11. Verwendung von inputStream.read() y StringBuilder (JDK). Warnung : Diese Lösung hat Probleme mit Unicode, z.B. mit russischem Text (funktioniert nur mit Nicht-Unicode-Text korrekt)

    StringBuilder sb = new StringBuilder();
    for (int ch; (ch = inputStream.read()) != -1; ) {
        sb.append((char) ch);
    }
    return sb.toString();

Warnung :

  1. Die Lösungen 4, 5 und 9 wandeln verschiedene Zeilenumbrüche in einen einzigen um.

  2. Lösung 11 kann nicht korrekt mit Unicode-Text arbeiten

Leistungstests

Leistungstests für kleine String (Länge = 175), url in github (Modus = Durchschnittszeit, System = Linux, Punktzahl 1,343 ist die beste):

              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

Leistungstests für große String (Länge = 50100), url in github (Modus = Durchschnittszeit, System = Linux, Punktzahl 200,715 ist die beste):

               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

Diagramme (Leistungstests in Abhängigkeit von der Länge des Eingabestroms im Windows 7-System)
enter image description here

Leistungstest (durchschnittliche Zeit) in Abhängigkeit von der Länge des Eingabestroms in einem Windows 7-System:

 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

0 Stimmen

Gute Arbeit. Könnte nützlich sein, um eine tl;dr Zusammenfassung am Ende, dh werfen die Lösungen, die Probleme mit Zeilenumbrüchen / Unicode haben und dann (von denen, die bleiben) sagen, die am schnellsten mit oder ohne externe Bibliotheken.

100 Stimmen

Diese Antwort scheint unvollständig zu sein

3 Stimmen

Ich war neugierig auf die Java 9 InputStream.transferTo und Java 10 Reader.transferTo Lösungen, die seit der Veröffentlichung dieser Antwort hinzugefügt wurden, habe ich den verlinkten Code überprüft und Benchmarks für sie hinzugefügt. Ich habe nur die "Big String"-Benchmarks getestet. InputStream.transferTo war von allen getesteten Lösungen am schnellsten und lief in 60 % der Zeit als test8 auf meinem Rechner getan hat. Reader.transferTo war langsamer als test8 , aber schneller als alle anderen Tests. Das heißt, er lief in 95% der Zeit als test1 Es handelt sich also nicht um eine wesentliche Verbesserung.

2756voto

Harry Lime Punkte 29086

Eine gute Möglichkeit, dies zu tun, ist die Verwendung von Apache Commons [IOUtils](https://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html) zum Kopieren der InputStream in eine StringWriter ... etwas wie

StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();

oder sogar

// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding); 

Alternativ können Sie auch Folgendes verwenden ByteArrayOutputStream wenn Sie Ihre Streams und Writers nicht vermischen wollen

0 Stimmen

Wurde die Funktion toString veraltet? Ich sehe IOUtils.convertStreamToString()

0 Stimmen

Ich habe einen durchsuchbaren Link zum eigentlichen Quellcode selbst als Referenz hinzugefügt. Ich glaube, dies ergänzt die Antwort für diejenigen, die sehen wollen, wie der Befehl funktioniert.

2364voto

Pavel Repin Punkte 30195

Hier ist ein Weg, der nur die Standard-Java-Bibliothek verwendet (beachten Sie, dass der Stream nicht geschlossen ist, Ihre Erfahrungen können variieren).

static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

Diesen Trick habe ich von "Blöde Scanner-Tricks" Artikel. Es funktioniert deshalb, weil Scanner durchläuft die Token im Datenstrom, und in diesem Fall trennen wir die Token durch "Beginn der Eingabegrenze" ( \A ), so dass wir nur ein Token für den gesamten Inhalt des Stroms erhalten.

Hinweis: Wenn Sie die Kodierung des Eingabestroms genau angeben müssen, können Sie das zweite Argument an Scanner Konstruktor, der angibt, welcher Zeichensatz verwendet werden soll (z. B. "UTF-8").

Der Hut geht auch an Jakob der mich einmal auf den genannten Artikel hingewiesen hat.

0 Stimmen

Sollten wir den Scanner nicht schließen, bevor wir den Wert zurückgeben?

0 Stimmen

@OlegMarkelov wahrscheinlich.

0 Stimmen

Würde dasselbe tun und die Ressource mit try with resource schließen try( java.util.Scanner s = new java.util.Scanner(is).useDelimiter(" \\A ")){ return s.hasNext() ? s.next() : ""; }

890voto

Chinnery Punkte 10029

Apache Commons erlaubt:

String myString = IOUtils.toString(myInputStream, "UTF-8");

Natürlich können Sie auch andere Zeichenkodierungen als UTF-8 wählen.

Siehe auch: ( Dokumentation )

1 Stimmen

Versuch, InputStream zurückzubekommen, funktioniert nicht stackoverflow.com/q/66349701/3425489

321voto

Paul de Vrieze Punkte 4851

Unter Berücksichtigung der Datei sollte man sich zunächst eine java.io.Reader Instanz. Diese kann dann gelesen und zu einer StringBuilder (wir brauchen keine StringBuffer wenn wir nicht in mehreren Threads darauf zugreifen, und StringBuilder ist schneller). Der Trick dabei ist, dass wir in Blöcken arbeiten und daher keine weiteren Pufferströme benötigen. Die Blockgröße wird für die Leistungsoptimierung zur Laufzeit parametriert.

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();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X