Zuverlässige Möglichkeit, eine Datei in ein Byte zu konvertieren []


83

Ich habe den folgenden Code im Web gefunden:

private byte [] StreamFile(string filename)
{
   FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read);

   // Create a byte array of file stream length
   byte[] ImageData = new byte[fs.Length];

   //Read block of bytes from stream into the byte array
   fs.Read(ImageData,0,System.Convert.ToInt32(fs.Length));

   //Close the File Stream
   fs.Close();
   return ImageData; //return the byte data
}

Ist es zuverlässig genug, um eine Datei in c # in Byte [] zu konvertieren, oder gibt es eine bessere Möglichkeit, dies zu tun?


3
Sie sollten fs.Close()den finally-Teil einer try-finally-Anweisung einfügen, die den Rest des Codes enthält, um sicherzustellen, dass er Closetatsächlich aufgerufen wird.
Joren

Antworten:


217
byte[] bytes = System.IO.File.ReadAllBytes(filename);

Das sollte den Trick machen. ReadAllBytes öffnet die Datei, liest ihren Inhalt in ein neues Byte-Array und schließt sie dann. Hier ist die MSDN-Seite für diese Methode.


Würde dies eine Dateisperre verursachen?
JL.

Ich meine - wird die Datei nach dem Auffüllen des Bytes [] nicht immer noch gesperrt?
JL.

3
Nein, das würde es nicht - die Datei wird geschlossen, sobald das Byte-Array gefüllt ist.
Erik Forbes

4
Das einzige kleine Problem dabei ist, dass bei einer großen Datei (z. B. 500 MB oder 1 GB usw.) so viel Speicher für Ihr Byte-Array reserviert wird. Manchmal lohnt es sich also, eine .Read (..) zu durchlaufen und sie langsam herauszunehmen. Das hängt natürlich alles von Ihrer Dateigröße ab. :)
Joshua

3
Dies schlägt fehl, wenn die Datei durch einen anderen Prozess geöffnet wird. Die OP-Methode funktioniert mit dem Hinzufügen von FileShare.ReadWriteafterFile.Read
Motes

27
byte[] bytes = File.ReadAllBytes(filename) 

oder ...

var bytes = File.ReadAllBytes(filename) 

13
Ernsthaft? 'var' ist in diesem Fall durchaus akzeptabel - der Rückgabetyp ist im Namen der Methode eindeutig angegeben ...
Erik Forbes

4
+1 für die ursprüngliche Verwendung var. Es ist meine persönliche Meinung (und die vieler anderer), dass es so oft wie möglich verwendet werden sollte. :) Die Angelegenheit wurde bereits mehrmals auf dieser Seite besprochen.
Noldorin

8
Auch +1 für die Verwendung von var ... @silky, ich denke, jeder kann eine Meinung darüber haben, ob neue Sprachfunktionen verwendet werden sollen oder nicht, aber eine Antwort herabzustimmen, weil sie nicht Ihrer Meinung entspricht, ist nicht so Worum ging es in diesem Forum? es hat sicherlich wenig mit JLs Frage zu tun.
Charles Bretana

6
Ich denke, Sie sollten beim Downvoting mehr als nur persönliche Vorlieben berücksichtigen. Dies ist eine absolut gültige Antwort, mit oder ohne var. Ich neige dazu zu denken, dass jeder Programmierer, der Typen manuell und explizit buchstabieren muss, auf einer zu niedrigen Abstraktionsebene arbeitet. Es sollte keine Rolle spielen, was der genaue Typ der Variablen ist, sondern nur, wofür die Variable ist . Wenn die Bytes aus der Datei gespeichert werden, sollte dies von Bedeutung sein. Nicht, ob es sich um eine Liste, ein Array oder einen MyCustomContainer handelt.
Jalf

8
Wenn das varfür die eigentliche Antwort überhaupt relevant gewesen wäre, hätte es Sinn gemacht, über die Verwendung zu streiten. Aber hier ist der wichtige Teil der Antwort gerecht File.ReadAllBytes(filename). Wie und ob das Ergebnis in einer Variablen gespeichert wird, ist ebenso irrelevant wie die Benennung der Variablen oder das Leerzeichen nach dem =.
Jalf

12

Nicht zu wiederholen, was alle bereits gesagt haben, sondern das folgende Spickzettel für Dateimanipulationen griffbereit zu halten:

  1. System.IO.File.ReadAllBytes(filename);
  2. File.Exists(filename)
  3. Path.Combine(folderName, resOfThePath);
  4. Path.GetFullPath(path); // converts a relative path to absolute one
  5. Path.GetExtension(path);

6

All diese Antworten mit .ReadAllBytes(). Eine andere ähnliche Frage (ich sage nicht doppelt, da sie versuchten, ihren Code umzugestalten) wurde hier zu SO gestellt: Der beste Weg, eine große Datei in ein Byte-Array in C # einzulesen?

Zu einem der Beiträge wurde ein Kommentar abgegeben zu .ReadAllBytes():

File.ReadAllBytes throws OutOfMemoryException with big files (tested with 630 MB file 
and it failed)  juanjo.arana Mar 13 '13 at 1:31

Ein besserer Ansatz für mich wäre so etwas mit BinaryReader:

public static byte[] FileToByteArray(string fileName)
{
    byte[] fileData = null;

    using (FileStream fs = File.OpenRead(fileName)) 
    { 
        var binaryReader = new BinaryReader(fs); 
        fileData = binaryReader.ReadBytes((int)fs.Length); 
    }
    return fileData;
}

Aber das bin nur ich ...

Dies alles setzt natürlich voraus, dass Sie über den Speicher verfügen, um das nach dem byte[]Einlesen zu verarbeiten, und ich habe nicht File.Existsüberprüft, ob die Datei vorhanden ist, bevor Sie fortfahren, wie Sie dies vor dem Aufrufen dieses Codes tun würden.


1
Es liegt ein Fehler in Ihrem Code vor. Sie benötigen das Neue nicht in der using-Anweisung, die verwendet werden muss (FileStream fs = File.OpenRead (fileName)
JoseR

Nicht so sehr ein Fehler (ich glaube, der Code würde immer noch kompiliert), aber ich habe ihn trotzdem entfernt. Guter Fang.
vapcguy

3

sieht als generische Version gut genug aus. Sie können es an Ihre Bedürfnisse anpassen, wenn sie spezifisch genug sind.

Testen Sie auch auf Ausnahmen und Fehlerbedingungen, z. B. dass eine Datei nicht vorhanden ist oder nicht gelesen werden kann usw.

Sie können auch Folgendes tun, um Platz zu sparen:

 byte[] bytes = System.IO.File.ReadAllBytes(filename);

2

Andere haben festgestellt, dass Sie die eingebaute verwenden können File.ReadAllBytes. Die integrierte Methode ist in Ordnung, aber es ist erwähnenswert, dass der Code, den Sie oben veröffentlichen, aus zwei Gründen fragil ist:

  1. Streamis IDisposable- Sie sollten die FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)Initialisierung in eine using-Klausel einfügen, um sicherzustellen, dass die Datei geschlossen ist. Andernfalls kann der Stream geöffnet bleiben, wenn ein Fehler auftritt. Dies bedeutet, dass die Datei gesperrt bleibt - und dies kann später zu anderen Problemen führen.
  2. fs.Readliest möglicherweise weniger Bytes als Sie anfordern. Im Allgemeinen liest die .ReadMethode einer StreamInstanz mindestens ein Byte, aber nicht unbedingt alle Bytes, nach denen Sie fragen. Sie müssen eine Schleife schreiben, die das Lesen wiederholt, bis alle Bytes gelesen sind. Diese Seite erklärt dies ausführlicher.
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.