Wie lese ich eine ganze InputStream
in ein Byte-Array?
Konvertieren Sie InputStream in ein Byte-Array in Java
JGC
Adamski
Sie müssen jedes Byte von Ihrem lesen InputStream
und schreibe es an a ByteArrayOutputStream
.
Sie können dann das zugrunde liegende Byte-Array durch Aufrufen abrufen toByteArray()
:
InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
-
Was ist mit der Größe des neu erstellten Bytes?[]. Warum ist es 16384? Wie kann ich genau die richtige Größe bestimmen? Danke sehr.
– Ondrej Bozek
3. April 2012 um 9:45 Uhr
-
16384 ist eine ziemlich willkürliche Wahl, obwohl ich Potenzen von 2 bevorzuge, um die Wahrscheinlichkeit zu erhöhen, dass das Array an Wortgrenzen ausgerichtet wird. Die Antwort von pihentagy zeigt, wie Sie die Verwendung eines Zwischenpuffers vermeiden können, sondern ein Array der richtigen Größe zuweisen. Wenn Sie es nicht mit großen Dateien zu tun haben, bevorzuge ich persönlich den obigen Code, der eleganter ist und für InputStreams verwendet werden kann, bei denen die Anzahl der zu lesenden Bytes nicht im Voraus bekannt ist.
– Adamsky
3. April 2012 um 11:33 Uhr
-
@Adamski Ist das Erstellen eines Arrays von Bytes nicht viel größer als Sie erwarten, dass Daten im Stream sein würden, den Speicher verschwenden?
– Paul Brewczyński
29. Juni 2013 um 16:38 Uhr
-
@bluesm: Ja das ist richtig. In meinem Beispiel ist das Byte-Array jedoch nur 16 KB groß und nach heutigen Maßstäben so winzig. Auch dieser Speicher wird natürlich danach wieder freigegeben.
– Adamsky
4. Juli 2013 um 7:36 Uhr
-
@Adamski Viele Infrastrukturhardware, Webserver und Komponenten auf Betriebssystemebene verwenden 4K-Puffer, um Daten zu verschieben. Das ist der Grund für die genaue Zahl, aber der Hauptpunkt ist, dass Sie durch Überschreiten von 4K einen so geringen Leistungsschub erzielen dass es allgemein als Speicherverschwendung angesehen wird. Ich gehe davon aus, dass dies der Fall ist still wahr, weil es jahrzehntealtes Wissen ist, das ich hatte!
– Benutzer2080225
30. März 2017 um 14:14 Uhr
-
Java-Dokumentation “Beachten Sie, dass diese Methode für einfache Fälle gedacht ist, in denen es bequem ist, alle Bytes in ein Byte-Array zu lesen. Sie ist nicht zum Lesen von Eingabeströmen mit großen Datenmengen gedacht.” und tatsächlich war es von meinem Test auf 8192 beschränkt (undokumentiert). Verwenden Sie es für Testzwecke, aber nicht in der Produktion.
– pdem
17. Dezember 2021 um 14:52 Uhr
-
@pdem es gibt kein solches Limit. Ich habe es gerade überprüft, indem ich eine 2-GiB-Datei in den Speicher gelesen habe. Es funktioniert, solange ein entsprechend großes Array zugewiesen werden kann. Wenn Sie unterschiedliche Ergebnisse erhalten, ist dies ein Problem Ihres Testaufbaus. Der Punkt, an dem Sie sollte nicht solch große Dateien in den Speicher zu lesen, sie aber lieber beim Lesen zu verarbeiten, ist eine ganz andere Sache. Dies gilt offensichtlich für alle in den Fragen und Antworten vorgestellten Lösungen, da es bei allen darum geht, eine ganze Datei in den Speicher einzulesen.
– Holger
17. Dezember 2021 um 15:04 Uhr
-
Nun, Sie sind sehr reaktiv, ich habe 2 jdk (11 17) getestet und es funktioniert mit einem großen ByteInputstream, wie Sie sagten, also schätze ich, dass es ein Problem mit May API mit Javamail gibt: Ich bekomme Dateien von einem Mimemessage-Inhalt. Seltsam ist, dass der mit Javamail zusammenhängende Fehler beim klassischen manuellen Lesen nicht auftaucht.
– pdem
17. Dezember 2021 um 15:21 Uhr
-
Tut dies spezifisch
InputStream
überschreibenreadAllBytes()
oderreadNBytes
?– Holger
17. Dezember 2021 um 15:28 Uhr
-
Klingt, als wäre es eine eigene Frage wert.
– Holger
20. Dezember 2021 um 8:34 Uhr
dermoritz
Verwenden Sie Vanille-Javas DataInputStream
und sein readFully
Methode (existiert seit mindestens Java 1.4):
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
Es gibt einige andere Varianten dieser Methode, aber ich verwende sie die ganze Zeit für diesen Anwendungsfall.
-
+1 für die Verwendung der Standardbibliotheken anstelle einer Abhängigkeit von Drittanbietern. Leider funktioniert es bei mir nicht, weil ich die Länge des Streams im Voraus nicht kenne.
– Andreas Spencer
7. Juni 2012 um 9:28 Uhr
-
@janus es ist eine “Datei”. Dieser Weg funktioniert nur, wenn Sie die Länge der Datei oder die Anzahl der zu lesenden Bytes kennen.
– Dermoritz
28. Juli 2013 um 9:49 Uhr
-
Interessante Sache, aber Sie müssen die genaue Länge des (Teils des) Streams kennen, um lesen zu können. Außerdem die Klasse
DataInputStream
wird hauptsächlich verwendet, um primäre Typen (Longs, Shorts, Chars …) aus einem Stream zu lesen, sodass wir diese Verwendung als Missbrauch der Klasse ansehen können.– Olivier Faucheux
8. April 2015 um 11:51 Uhr
-
Wenn Sie die Länge der aus dem Stream zu lesenden Daten bereits kennen, ist dies nicht besser als
InputStream.read
.– Logan-Abholung
12. Oktober 2016 um 3:57 Uhr
-
@LoganPickup InputStream.read garantiert nicht, dass alle angeforderten Bytes zurückgegeben werden!
– Ray Hulha
15. Oktober 2018 um 3:32 Uhr
Joachim Sauer
Wenn Sie zufällig verwenden Google Guavees wird so einfach wie die Verwendung sein ByteStreams
:
byte[] bytes = ByteStreams.toByteArray(inputStream);
-
+1 für die Verwendung der Standardbibliotheken anstelle einer Abhängigkeit von Drittanbietern. Leider funktioniert es bei mir nicht, weil ich die Länge des Streams im Voraus nicht kenne.
– Andreas Spencer
7. Juni 2012 um 9:28 Uhr
-
@janus es ist eine “Datei”. Dieser Weg funktioniert nur, wenn Sie die Länge der Datei oder die Anzahl der zu lesenden Bytes kennen.
– Dermoritz
28. Juli 2013 um 9:49 Uhr
-
Interessante Sache, aber Sie müssen die genaue Länge des (Teils des) Streams kennen, um lesen zu können. Außerdem die Klasse
DataInputStream
wird hauptsächlich verwendet, um primäre Typen (Longs, Shorts, Chars …) aus einem Stream zu lesen, sodass wir diese Verwendung als Missbrauch der Klasse ansehen können.– Olivier Faucheux
8. April 2015 um 11:51 Uhr
-
Wenn Sie die Länge der aus dem Stream zu lesenden Daten bereits kennen, ist dies nicht besser als
InputStream.read
.– Logan-Abholung
12. Oktober 2016 um 3:57 Uhr
-
@LoganPickup InputStream.read garantiert nicht, dass alle angeforderten Bytes zurückgegeben werden!
– Ray Hulha
15. Oktober 2018 um 3:32 Uhr
Arne Burmeister
Wie immer auch Frühlingsrahmen (Spring-Core seit 3.2.2) hat etwas für Sie: StreamUtils.copyToByteArray()
-
Wie die meisten anderen wollte ich vermeiden, eine Bibliothek eines Drittanbieters für etwas so Einfaches zu verwenden, aber Java 9 ist im Moment keine Option … zum Glück habe ich bereits Spring verwendet.
– Scottysseus
15. Oktober 2018 um 21:54 Uhr
Siehe umgekehrt: byte[] zu InputStream hier: stackoverflow.com/questions/2091454/…
– David d C e Freitas
22. September 2011 um 10:34 Uhr