Es kommt darauf an, was für Sie am besten bedeutet. In Bezug auf die Produktivität sollten Sie das Rad nicht neu erfinden und Apache Commons verwenden. Welches ist hier IOUtils.toByteArray(InputStream input).
@ymajoros: So wahr! Ich hätte lieber ein paar zusätzliche Codezeilen als eine weitere Abhängigkeit. Abhängigkeiten haben versteckte Kosten. Sie müssen mit dieser Bibliothek auf dem neuesten Stand bleiben, die Abhängigkeit in Ihre Build-Skripte einbeziehen usw., sie an Personen weitergeben, die Ihren Code verwenden usw. usw. Wenn Sie bereits eine Bibliothek verwenden, die Code dafür hat, dann verwenden Sie diesen, würde ich sagen schreibe es selbst.
Stijn de Witt
11
Dies beantwortet die Frage, wie eine Datei gelesen werden soll, nicht jedoch die Frage, wie ein Objekt vom Typ java.IO.File in Byte [] konvertiert werden soll.
Ingo
5
Wie wird dies verwendet, um ein Filezu lesen byte[]? Ich benutze Java6, daher kann ich die NIO-Methoden nicht verwenden :(
PASTRY
4
@ymajoros Würden Sie uns bitte eine "Standard-3-Zeilen-Lösung" mitteilen, damit wir uns nicht auf eine Neuerfindung der Radabhängigkeit verlassen müssen?
Matto
3
@ Matto: irgendwelche? Siehe andere Antworten, z. B. Files.readAllBytes (). Einfach, keine Abhängigkeit.
@ aldo.roman.nurena JDK7 hat eine File.toPath () -Methode eingeführt, mit der Sie ein Pfadobjekt erhalten.
KevinL
6
Sie können einen Pfad aus einer Datei abrufen. Versuchen Sie: File file = new File ("/ path"); Pfad path = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (Pfad);
Gfelisberto
2
Wie wird das Schließen von Dateien in java.nio gehandhabt - mit anderen Worten, sollte der obige Code etwas schließen?
Akauppi
4
@akauppi Siehe den Link in der Antwort: "Die Methode stellt sicher, dass die Datei geschlossen wird ..."
Dies ist jetzt eine bessere Wahl als die akzeptierte Antwort, für die Apache Commons erforderlich ist.
James.garriss
1
Danke :) Ich brauchte auch diesen: String text = neuer String (Files.readAllBytes (neue Datei ("/ path / to / file"). ToPath ())); Das ist ursprünglich von stackoverflow.com/a/26888713/1257959
cgl
5
In Android muss die Mindest-API-Stufe 26 sein.
Ashutosh Chamoli
2
Sie müssen hinzufügen import java.nio.file.Files;und import java.nio.file.Paths;wenn Sie noch nicht.
Sam
164
import java.io.RandomAccessFile;RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Sie müssen den Rückgabewert von f.read () überprüfen. Hier kann es manchmal vorkommen, dass Sie nicht die gesamte Datei lesen.
Bugs_
8
Eine solche Situation kann nur auftreten, wenn sich die Datei während des Lesens ändert. In allen anderen Fällen wird eine IOException ausgelöst. Um dieses Problem zu beheben, empfehle ich, die Datei im Lese- / Schreibmodus zu öffnen: RandomAccessFile (Dateiname, "rw")
Dmitry Mitskevich
5
Ich könnte mir andere Quellen vorstellen, um nur einen Teil der Datei zu lesen (Datei befindet sich auf einer Netzwerkfreigabe ...). ReadFully () hat den Vertrag, nach dem Sie suchen.
DThought
3
Denken Sie daran, dass RandomAccessFile nicht threadsicher ist. In einigen Fällen kann daher eine Synchronisierung erforderlich sein.
Bancer
@DmitryMitskevich Es gibt auch andere Fälle auf Dateisystemen, die möglicherweise nicht konform sind. Zum Beispiel kann das Lesen von "Dateien" in / proc / unter Linux zu kurzen Lesevorgängen führen (dh Sie benötigen eine Schleife, um alles zu lesen)
Nr.
78
Grundsätzlich muss man es im Speicher lesen. Öffnen Sie die Datei, ordnen Sie das Array zu und lesen Sie den Inhalt der Datei in das Array.
Dies führt zu unnötigem Kopieren des Dateiinhalts (tatsächlich werden die Daten dreimal kopiert: von Datei zu buffer, von bufferzu ByteArrayOutputStream, von ByteArrayOutputStreamzu dem tatsächlich resultierenden Array).
Sie müssen auch sicherstellen, dass Sie nur Dateien bis zu einer bestimmten Größe im Speicher lesen (dies ist normalerweise anwendungsabhängig) :-).
Sie müssen auch die IOExceptionAußenseite der Funktion behandeln.
Ein anderer Weg ist folgender:
publicbyte[] read(File file)throwsIOException,FileTooBigException{if(file.length()> MAX_FILE_SIZE){thrownewFileTooBigException(file);}byte[] buffer =newbyte[(int) file.length()];InputStream ios =null;try{
ios =newFileInputStream(file);if(ios.read(buffer)==-1){thrownewIOException("EOF reached while trying to read the whole file");}}finally{try{if(ios !=null)
ios.close();}catch(IOException e){}}return buffer;}
Dies hat kein unnötiges Kopieren.
FileTooBigExceptionist eine benutzerdefinierte Anwendungsausnahme. Die MAX_FILE_SIZEKonstante ist ein Anwendungsparameter.
Für große Dateien sollten Sie wahrscheinlich einen Stream-Verarbeitungsalgorithmus in Betracht ziehen oder die Speicherzuordnung verwenden (siehe java.nio).
Die Anweisung "ios.read (buffer)" im zweiten Beispiel liest nur die ersten 4096 Bytes der Datei ein (unter der Annahme des gleichen 4k-Puffers wie im ersten Beispiel). Damit das zweite Beispiel funktioniert, muss sich der Lesevorgang in einer while-Schleife befinden, die das Ergebnis auf -1 überprüft (Dateiende erreicht).
Stijn de Witt
Entschuldigung, lehne meine obige Bemerkung ab und habe den Anweisungseinstellungspuffer auf Dateilänge verpasst. Trotzdem gefällt mir das erste Beispiel viel besser. Das gleichzeitige Einlesen einer ganzen Datei in einen Puffer ist nicht skalierbar. Wenn die Datei groß ist, besteht die Gefahr, dass nicht genügend Speicherplatz zur Verfügung steht.
Stijn de Witt
Der "einfachste" Weg würde das Ausprobieren von Ressourcen nutzen.
import org.apache.commons.io.FileUtils;publicclassProgram{publicstaticvoid main(String[] args)throwsIOException{File file =newFile(args[0]);// assume args[0] is the path to filebyte[] data =FileUtils.readFileToByteArray(file);...}}
Es ist absolut nicht erforderlich, die Speicherzuordnung zu verwenden, wenn Sie die Datei nur einmal lesen möchten. Dadurch wird doppelt so viel Speicher benötigt wie bei einem normalen FileInputStream.
James
1
Leider wird MappedByteBuffer nicht automatisch freigegeben.
Tom Hawtin - Tackline
2
Das neue Beispiel enthält printStackTrace, die klassische Behandlung defekter Ausnahmen.
James
Ich stimme zu. Es ist das Standardmaterial, das Eclipse einfügt. Ich denke, ich sollte die Ausnahme erneut auslösen!
Amit
Ich habe nio verglichen, um ein Byte [] aus einer Datei zu erstellen. Anders als bei Verwendung eines direkten Puffers wird tatsächlich doppelt so viel Speicher benötigt. Obwohl es für sehr große Dateien schneller ist (ungefähr doppelt so schnell wie ein gepuffertes E / A für 200 Millionen), scheint es für Dateien um 5 Millionen um den Faktor 5 zu verlieren.
Chaffers
22
Wenn Sie nicht über Java 8 verfügen und mir zustimmen, ist es eine schlechte Idee, eine umfangreiche Bibliothek einzuschließen, um das Schreiben einiger Codezeilen zu vermeiden:
publicstaticbyte[] readBytes(InputStream inputStream)throwsIOException{byte[] b =newbyte[1024];ByteArrayOutputStream os =newByteArrayOutputStream();int c;while((c = inputStream.read(b))!=-1){
os.write(b,0, c);}return os.toByteArray();}
Der Anrufer ist für das Schließen des Streams verantwortlich.
// Returns the contents of the file in a byte array.publicstaticbyte[] getBytesFromFile(File file)throwsIOException{// Get the size of the filelong length = file.length();// You cannot create an array using a long type.// It needs to be an int type.// Before converting to an int type, check// to ensure that file is not larger than Integer.MAX_VALUE.if(length >Integer.MAX_VALUE){// File is too largethrownewIOException("File is too large!");}// Create the byte array to hold the databyte[] bytes =newbyte[(int)length];// Read in the bytesint offset =0;int numRead =0;InputStream is =newFileInputStream(file);try{while(offset < bytes.length
&&(numRead=is.read(bytes, offset, bytes.length-offset))>=0){
offset += numRead;}}finally{
is.close();}// Ensure all the bytes have been read inif(offset < bytes.length){thrownewIOException("Could not completely read file "+file.getName());}return bytes;}
Fügen Sie außerdem numRead in die Schleife ein. Deklarieren Sie Variablen im kleinstmöglichen gültigen Bereich. Das Platzieren außerhalb der while-Schleife ist nur erforderlich, um diesen komplizierten "while" -Test zu ermöglichen. Es ist besser, den EOF-Test innerhalb der Schleife durchzuführen (und eine EOFException auszulösen, wenn dies auftritt).
Erickson
throw new IOException("File is too large!");Was sollen wir tun, wenn die Datei zu groß ist? Gibt es auch ein Beispiel dafür?
Fer
21
Einfache Möglichkeit:
File fff =newFile("/path/to/file");FileInputStream fileInputStream =newFileInputStream(fff);// int byteLength = fff.length(); // In android the result of file.length() is longlong byteLength = fff.length();// byte count of the file-contentbyte[] filecontent =newbyte[(int) byteLength];
fileInputStream.read(filecontent,0,(int) byteLength);
Kannst du das hier erklären? Warum hast du einen Streit?
Muhammad Sadiq
3
Nichts Besonderes, aber Sie sagen am einfachsten und ich sehe einfachere Lösungen -> meiner Meinung nach ist es nicht die einfachste. Vielleicht war es vor ein paar Jahren, aber die Welt verändert sich. Ich würde meine eigenen Lösungen nicht mit einer solchen Aussage kennzeichnen. ;) Wenn du nur geschrieben hättest "Meiner Meinung nach ist das Einfachste ..." oder "Das Einfachste, das ich gefunden habe ..." Willst du dich nicht stören, dachte nur nett, dies zu kommunizieren.
BlondCode
@ MuhammadSadiq: Importiere nichts .*, es wird als schlechte Praxis angesehen.
Es deckt den Eckfall ab, in dem Dateien eine Länge von 0 melden, aber dennoch Inhalt haben
Es ist stark optimiert. Sie erhalten eine OutOfMemoryException, wenn Sie versuchen, eine große Datei einzulesen, bevor Sie überhaupt versuchen, die Datei zu laden. (Durch geschickte Verwendung von file.length ())
Verwenden Sie denselben Ansatz wie die Antwort des Community-Wikis, aber sauberer und sofort kompilierbarer Ansatz (bevorzugter Ansatz, wenn Sie keine Apache Commons-Bibliotheken importieren möchten, z. B. unter Android):
publicstaticbyte[] getFileBytes(File file)throwsIOException{ByteArrayOutputStream ous =null;InputStream ios =null;try{byte[] buffer =newbyte[4096];
ous =newByteArrayOutputStream();
ios =newFileInputStream(file);int read =0;while((read = ios.read(buffer))!=-1)
ous.write(buffer,0, read);}finally{try{if(ous !=null)
ous.close();}catch(IOException e){// swallow, since not that important}try{if(ios !=null)
ios.close();}catch(IOException e){// swallow, since not that important}}return ous.toByteArray();}
Es gibt bereits eine Antwort mit diesem Vorschlag von Tom im Jahr 2009
Knut Herrmann
7
ReadFully Liest b.Länge Bytes aus dieser Datei in das Byte-Array, beginnend mit dem aktuellen Dateizeiger. Diese Methode liest wiederholt aus der Datei, bis die angeforderte Anzahl von Bytes gelesen wurde. Diese Methode blockiert, bis die angeforderte Anzahl von Bytes gelesen, das Ende des Streams erkannt oder eine Ausnahme ausgelöst wurde.
RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Wenn Sie Bytes in einen vorab zugewiesenen Bytepuffer einlesen möchten, kann diese Antwort hilfreich sein.
Ihre erste Vermutung wäre wahrscheinlich zu verwenden InputStream read(byte[]). Diese Methode weist jedoch einen Fehler auf, der die Verwendung unangemessen schwierig macht: Es gibt keine Garantie dafür, dass das Array tatsächlich vollständig gefüllt ist, selbst wenn kein EOF auftritt.
Schauen Sie sich stattdessen an DataInputStream readFully(byte[]). Dies ist ein Wrapper für Eingabestreams und weist das oben genannte Problem nicht auf. Darüber hinaus wird diese Methode ausgelöst, wenn EOF auftritt. Viel schöner.
Die folgende Methode konvertiert eine java.io.File nicht nur in ein Byte [], sondern hat auch festgestellt, dass dies die schnellste Methode zum Einlesen einer Datei ist, wenn viele verschiedene Lesemethoden für Java-Dateien gegeneinander getestet werden :
Lassen Sie mich eine weitere Lösung hinzufügen, ohne Bibliotheken von Drittanbietern zu verwenden. Es wird ein von Scott vorgeschlagenes Ausnahmebehandlungsmuster ( Link ) wiederverwendet . Und ich habe den hässlichen Teil in eine separate Nachricht verschoben (ich würde mich in einer FileUtils-Klasse verstecken;))
publicvoid someMethod(){finalbyte[] buffer = read(newFile("test.txt"));}privatebyte[] read(finalFile file){if(file.isDirectory())thrownewRuntimeException("Unsupported operation, file "+ file.getAbsolutePath()+" is a directory");if(file.length()>Integer.MAX_VALUE)thrownewRuntimeException("Unsupported operation, file "+ file.getAbsolutePath()+" is too big");Throwable pending =null;FileInputStream in =null;finalbyte buffer[]=newbyte[(int) file.length()];try{
in =newFileInputStream(file);
in.read(buffer);}catch(Exception e){
pending =newRuntimeException("Exception occured on reading file "+ file.getAbsolutePath(), e);}finally{if(in !=null){try{
in.close();}catch(Exception e){if(pending ==null){
pending =newRuntimeException("Exception occured on closing file"+ file.getAbsolutePath(), e);}}}if(pending !=null){thrownewRuntimeException(pending);}}return buffer;}
Verwenden Sie keine hohlen Fangblöcke. es macht das Debuggen schwierig.
Sapphire_Brick
1
//The file that you wanna convert into byte[]File file=newFile("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4");FileInputStream fileInputStream=newFileInputStream(file);byte[] data=newbyte[(int) file.length()];BufferedInputStream bufferedInputStream=newBufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);//Now the bytes of the file are contain in the "byte[] data"
Während dieser Code möglicherweise eine Lösung für die Frage bietet, ist es besser, einen Kontext hinzuzufügen, warum / wie er funktioniert. Dies kann zukünftigen Benutzern helfen, zu lernen und dieses Wissen auf ihren eigenen Code anzuwenden. Es ist auch wahrscheinlich, dass Sie positive Rückmeldungen von Benutzern in Form von Upvotes erhalten, wenn der Code erklärt wird.
Borchvm
Nun, das ist der wichtige Teil, den ich in zukünftigen Beiträgen berücksichtigen werde. Vielen Dank für Ihre nützlichen Erkenntnisse.
Antworten:
Es kommt darauf an, was für Sie am besten bedeutet. In Bezug auf die Produktivität sollten Sie das Rad nicht neu erfinden und Apache Commons verwenden. Welches ist hier
IOUtils.toByteArray(InputStream input)
.quelle
File
zu lesenbyte[]
? Ich benutze Java6, daher kann ich die NIO-Methoden nicht verwenden :(Ab JDK 7 können Sie verwenden
Files.readAllBytes(Path)
.Beispiel:
quelle
Seit JDK 7 - ein Liner:
Keine externen Abhängigkeiten erforderlich.
quelle
import java.nio.file.Files;
undimport java.nio.file.Paths;
wenn Sie noch nicht.Dokumentation für Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
quelle
Grundsätzlich muss man es im Speicher lesen. Öffnen Sie die Datei, ordnen Sie das Array zu und lesen Sie den Inhalt der Datei in das Array.
Der einfachste Weg ist ähnlich:
Dies führt zu unnötigem Kopieren des Dateiinhalts (tatsächlich werden die Daten dreimal kopiert: von Datei zu
buffer
, vonbuffer
zuByteArrayOutputStream
, vonByteArrayOutputStream
zu dem tatsächlich resultierenden Array).Sie müssen auch sicherstellen, dass Sie nur Dateien bis zu einer bestimmten Größe im Speicher lesen (dies ist normalerweise anwendungsabhängig) :-).
Sie müssen auch die
IOException
Außenseite der Funktion behandeln.Ein anderer Weg ist folgender:
Dies hat kein unnötiges Kopieren.
FileTooBigException
ist eine benutzerdefinierte Anwendungsausnahme. DieMAX_FILE_SIZE
Konstante ist ein Anwendungsparameter.Für große Dateien sollten Sie wahrscheinlich einen Stream-Verarbeitungsalgorithmus in Betracht ziehen oder die Speicherzuordnung verwenden (siehe
java.nio
).quelle
Wie jemand sagte, haben Apache Commons File Utils möglicherweise das, wonach Sie suchen
Beispiel use (
Program.java
):quelle
Sie können dazu auch die NIO-API verwenden. Ich könnte dies mit diesem Code tun, solange die gesamte Dateigröße (in Bytes) in ein int passt.
Ich denke, es ist sehr schnell, da es MappedByteBuffer verwendet.
quelle
Wenn Sie nicht über Java 8 verfügen und mir zustimmen, ist es eine schlechte Idee, eine umfangreiche Bibliothek einzuschließen, um das Schreiben einiger Codezeilen zu vermeiden:
Der Anrufer ist für das Schließen des Streams verantwortlich.
quelle
quelle
throw new IOException("File is too large!");
Was sollen wir tun, wenn die Datei zu groß ist? Gibt es auch ein Beispiel dafür?Einfache Möglichkeit:
quelle
Einfachster Weg zum Lesen von Bytes aus einer Datei
quelle
.*
, es wird als schlechte Praxis angesehen.Guava hat Files.toByteArray () zu bieten. Es hat mehrere Vorteile:
quelle
quelle
Verwenden Sie denselben Ansatz wie die Antwort des Community-Wikis, aber sauberer und sofort kompilierbarer Ansatz (bevorzugter Ansatz, wenn Sie keine Apache Commons-Bibliotheken importieren möchten, z. B. unter Android):
quelle
Ich glaube, das ist der einfachste Weg:
quelle
ReadFully Liest b.Länge Bytes aus dieser Datei in das Byte-Array, beginnend mit dem aktuellen Dateizeiger. Diese Methode liest wiederholt aus der Datei, bis die angeforderte Anzahl von Bytes gelesen wurde. Diese Methode blockiert, bis die angeforderte Anzahl von Bytes gelesen, das Ende des Streams erkannt oder eine Ausnahme ausgelöst wurde.
quelle
Wenn Sie Bytes in einen vorab zugewiesenen Bytepuffer einlesen möchten, kann diese Antwort hilfreich sein.
Ihre erste Vermutung wäre wahrscheinlich zu verwenden
InputStream read(byte[])
. Diese Methode weist jedoch einen Fehler auf, der die Verwendung unangemessen schwierig macht: Es gibt keine Garantie dafür, dass das Array tatsächlich vollständig gefüllt ist, selbst wenn kein EOF auftritt.Schauen Sie sich stattdessen an
DataInputStream readFully(byte[])
. Dies ist ein Wrapper für Eingabestreams und weist das oben genannte Problem nicht auf. Darüber hinaus wird diese Methode ausgelöst, wenn EOF auftritt. Viel schöner.quelle
Die folgende Methode konvertiert eine java.io.File nicht nur in ein Byte [], sondern hat auch festgestellt, dass dies die schnellste Methode zum Einlesen einer Datei ist, wenn viele verschiedene Lesemethoden für Java-Dateien gegeneinander getestet werden :
java.nio.file.Files.readAllBytes ()
quelle
Lassen Sie mich eine weitere Lösung hinzufügen, ohne Bibliotheken von Drittanbietern zu verwenden. Es wird ein von Scott vorgeschlagenes Ausnahmebehandlungsmuster ( Link ) wiederverwendet . Und ich habe den hässlichen Teil in eine separate Nachricht verschoben (ich würde mich in einer FileUtils-Klasse verstecken;))
quelle
quelle
Eine andere Möglichkeit, Bytes aus Dateien zu lesen
quelle
quelle
Versuche dies :
quelle
In JDK8
quelle