Datei zu Byte [] in Java


757

Wie konvertiere ich a java.io.Filein a byte[]?


Eine Verwendung, die ich mir vorstellen kann, ist das Lesen von serialisierten Objekten aus einer Datei.
Mahm00d

2
Eine andere Möglichkeit besteht darin, den Dateityp mithilfe des Headers zu ermitteln.
James P.

Versuchen Sie dieses Byte [] bytes = null; BufferedInputStream fileInputStream = null; try {File file = neue Datei (filePath); fileInputStream = neuer BufferedInputStream (neuer FileInputStream (Datei)); // fileInputStream = Thread.currentThread (). getContextClassLoader (). getResourceAsStream (this.filePath); Bytes = neues Byte [(int) file.length ()]; fileInputStream.read (Bytes); } catch (FileNotFoundException ex) {throw ex; }
Rohit Chaurasiya

Antworten:


486

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).


29
@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.
Ymajoros

1292

Ab JDK 7 können Sie verwenden Files.readAllBytes(Path).

Beispiel:

import java.io.File;
import java.nio.file.Files;

File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());

10
Ich habe ein
Dateiobjekt

81
@ 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 ..."
Bernhard Barker

226

Seit JDK 7 - ein Liner:

byte[] array = Files.readAllBytes(Paths.get("/path/to/file"));

Keine externen Abhängigkeiten erforderlich.


13
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 = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

Dokumentation für Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html


2
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.

Der einfachste Weg ist ähnlich:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(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) {
        }

        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return ous.toByteArray();
}

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:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }

    byte[] buffer = new byte[(int) file.length()];
    InputStream ios = null;
    try {
        ios = new FileInputStream(file);
        if (ios.read(buffer) == -1) {
            throw new IOException(
                    "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).


ios muss außerhalb des Versuchs deklariert werden
Daryl Spitzer

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.
Sina Madani

Cool, aber ein bisschen wortreich.
Sapphire_Brick

77

Wie jemand sagte, haben Apache Commons File Utils möglicherweise das, wonach Sie suchen

public static byte[] readFileToByteArray(File file) throws IOException

Beispiel use ( Program.java):

import org.apache.commons.io.FileUtils;
public class Program {
    public static void main(String[] args) throws IOException {
        File file = new File(args[0]);  // assume args[0] is the path to file
        byte[] data = FileUtils.readFileToByteArray(file);
        ...
    }
}

23

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.

File f = new File("c:\\wscp.script");
FileInputStream fin = null;
FileChannel ch = null;
try {
    fin = new FileInputStream(f);
    ch = fin.getChannel();
    int size = (int) ch.size();
    MappedByteBuffer buf = ch.map(MapMode.READ_ONLY, 0, size);
    byte[] bytes = new byte[size];
    buf.get(bytes);

} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} finally {
    try {
        if (fin != null) {
            fin.close();
        }
        if (ch != null) {
            ch.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Ich denke, es ist sehr schnell, da es MappedByteBuffer verwendet.


2
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:

public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] b = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    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.


21
// Returns the contents of the file in a byte array.
    public static byte[] getBytesFromFile(File file) throws IOException {        
        // Get the size of the file
        long 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 large
            throw new IOException("File is too large!");
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;

        InputStream is = new FileInputStream(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 in
        if (offset < bytes.length) {
            throw new IOException("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 = new File("/path/to/file");
FileInputStream fileInputStream = new FileInputStream(fff);

// int byteLength = fff.length(); 

// In android the result of file.length() is long
long byteLength = fff.length(); // byte count of the file-content

byte[] filecontent = new byte[(int) byteLength];
fileInputStream.read(filecontent, 0, (int) byteLength);

Es gibt einfachere Wege, wie die bereits erwähnten Einzeiler.
Sapphire_Brick

@Sapphire_Brick Einfachere Wege ja - aber die Einzeiler passen nicht in alle Situationen. Wie Android.
Behr

17

Einfachster Weg zum Lesen von Bytes aus einer Datei

import java.io.*;

class ReadBytesFromFile {
    public static void main(String args[]) throws Exception {
        // getBytes from anyWhere
        // I'm getting byte array from File
        File file = null;
        FileInputStream fileStream = new FileInputStream(file = new File("ByteArrayInputStreamClass.java"));

        // Instantiate array
        byte[] arr = new byte[(int) file.length()];

        // read All bytes of File stream
        fileStream.read(arr, 0, arr.length);

        for (int X : arr) {
            System.out.print((char) X);
        }
    }
}

1
Ich argumentiere, der "einfachste Weg" zu sein :)
BlondCode

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.
Sapphire_Brick

13

Guava hat Files.toByteArray () zu bieten. Es hat mehrere Vorteile:

  1. Es deckt den Eckfall ab, in dem Dateien eine Länge von 0 melden, aber dennoch Inhalt haben
  2. 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 ())
  3. Sie müssen das Rad nicht neu erfinden.

12
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

File file = getYourFile();
Path path = file.toPath();
byte[] data = Files.readAllBytes(path);

Welches JDK-Level ist das?
Jonathan S. Fisher

11

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):

public static byte[] getFileBytes(File file) throws IOException {
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(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();
}

8

Ich glaube, das ist der einfachste Weg:

org.apache.commons.io.FileUtils.readFileToByteArray(file);

7
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 = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

5

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.


4

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

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class ReadFile_Files_ReadAllBytes {
  public static void main(String [] pArgs) throws IOException {
    String fileName = "c:\\temp\\sample-10KB.txt";
    File file = new File(fileName);

    byte [] fileBytes = Files.readAllBytes(file.toPath());
    char singleChar;
    for(byte b : fileBytes) {
      singleChar = (char) b;
      System.out.print(singleChar);
    }
  }
}

3

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

public void someMethod() {
    final byte[] buffer = read(new File("test.txt"));
}

private byte[] read(final File file) {
    if (file.isDirectory())
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is a directory");
    if (file.length() > Integer.MAX_VALUE)
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is too big");

    Throwable pending = null;
    FileInputStream in = null;
    final byte buffer[] = new byte[(int) file.length()];
    try {
        in = new FileInputStream(file);
        in.read(buffer);
    } catch (Exception e) {
        pending = new RuntimeException("Exception occured on reading file "
                + file.getAbsolutePath(), e);
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (Exception e) {
                if (pending == null) {
                    pending = new RuntimeException(
                        "Exception occured on closing file" 
                             + file.getAbsolutePath(), e);
                }
            }
        }
        if (pending != null) {
            throw new RuntimeException(pending);
        }
    }
    return buffer;
}

3
public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] buffer = new byte[32 * 1024];
    int bufferSize = 0;
    for (;;) {
        int read = inputStream.read(buffer, bufferSize, buffer.length - bufferSize);
        if (read == -1) {
            return Arrays.copyOf(buffer, bufferSize);
        }
        bufferSize += read;
        if (bufferSize == buffer.length) {
            buffer = Arrays.copyOf(buffer, bufferSize * 2);
        }
    }
}

1

Eine andere Möglichkeit, Bytes aus Dateien zu lesen

Reader reader = null;
    try {
        reader = new FileReader(file);
        char buf[] = new char[8192];
        int len;
        StringBuilder s = new StringBuilder();
        while ((len = reader.read(buf)) >= 0) {
            s.append(buf, 0, len);
            byte[] byteArray = s.toString().getBytes();
        }
    } catch(FileNotFoundException ex) {
    } catch(IOException e) {
    }
    finally {
        if (reader != null) {
            reader.close();
        }
    }

Verwenden Sie keine hohlen Fangblöcke. es macht das Debuggen schwierig.
Sapphire_Brick

1
//The file that you wanna convert into byte[]
File file=new File("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4"); 

FileInputStream fileInputStream=new FileInputStream(file);
byte[] data=new byte[(int) file.length()];
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);

//Now the bytes of the file are contain in the "byte[] data"

1
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.
Usama Mehmood

0

Versuche dies :

import sun.misc.IOUtils;
import java.io.IOException;

try {
    String path="";
    InputStream inputStream=new FileInputStream(path);
    byte[] data=IOUtils.readFully(inputStream,-1,false);
}
catch (IOException e) {
    System.out.println(e);
}

Dies erfordert eine bestimmte JRE-Implementierung, die die App beschädigt, wenn sie auf einer anderen JRE ausgeführt wird.
Rattaman

2
kleiner Fehler: ist IOException und nicht IOexception, aber danke :)
Matan Marciano

1
@MatanMarciano: mein schlechtes
Sapphire_Brick

-7

In JDK8

Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();

2
Lesen Sie die Frage meines französischsprachigen Freundes, sie fragt nach der Konvertierung in ein "Byte []", und Ihre Antwort liefert dies nicht.
Kaiser Keister

2
Dies bietet keine gleichmäßige Remote-Option für die Konvertierung in Byte []!
Anddo
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.