Manera confiable de convertir un archivo a un byte []

84

Encontré el siguiente código en la web:

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
}

¿Es lo suficientemente confiable como para convertir un archivo al byte [] en c #, o hay una mejor manera de hacerlo?

JL.
fuente
3
Debe colocar fs.Close()la parte final de una instrucción try-finalmente que incluya el resto del código, para asegurarse de Closeque realmente se llame.
Joren

Respuestas:

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

Eso debería hacer el truco. ReadAllBytes abre el archivo, lee su contenido en una nueva matriz de bytes y luego lo cierra. Aquí está la página de MSDN para ese método.

Erik Forbes
fuente
¿Causaría esto un bloqueo de archivo?
JL.
Quiero decir, una vez que se completa el byte [], ¿no se bloqueará el archivo?
JL.
3
No, no lo haría: el archivo se cierra tan pronto como se completa la matriz de bytes.
Erik Forbes
4
El único problema menor con esto es que si tiene un archivo grande (digamos 500 MB o 1 GB, etc.) asignará esa cantidad de memoria para su matriz de bytes. Entonces, a veces vale la pena recorrer un .Read (..) y sacarlo lentamente. Por supuesto, todo depende del tamaño de su archivo. :)
Joshua
3
Esto fallará si el archivo es abierto por otro proceso, el método OP funcionará con la adición de FileShare.ReadWriteafterFile.Read
Motes
28
byte[] bytes = File.ReadAllBytes(filename) 

o ...

var bytes = File.ReadAllBytes(filename) 
Brian Rasmussen
fuente
13
¿Seriamente? 'var' es perfectamente aceptable en este caso: el tipo de retorno se indica claramente en el nombre del método ...
Erik Forbes
4
+1 por usar originalmente var. Es mi opinión personal (y la de muchos otros), que debería usarse tanto como sea posible. :) El asunto ha sido discutido varias veces en este sitio antes, de hecho.
Noldorin
8
También +1 por usar var ... @silky, supongo que todos son libres de tener una opinión sobre si usar o no nuevas funciones de lenguaje cuando se presenten, pero rechazar una respuesta porque no se ajusta a su opinión no es de qué pensaba que trataba este foro. ciertamente tiene poco que ver con la pregunta de JL.
Charles Bretana
6
Creo que debería considerar más que una preferencia personal al votar en contra. Esta es una respuesta perfectamente válida, con o sin var. Tiendo a pensar que cualquier programador que necesite deletrear tipos de forma manual y explícita está trabajando con un nivel de abstracción demasiado bajo. No debe importa lo que el tipo exacto de la variable es, sólo lo que la variable es para . Si almacena los bytes del archivo, entonces eso debería ser lo que importa. No si es una lista o una matriz o MyCustomContainer.
Jalf
8
Si varhubiera sido relevante para la respuesta real, discutir sobre su uso habría tenido sentido. Pero aquí, la parte importante de la respuesta es justa File.ReadAllBytes(filename). Cómo y si el resultado se almacena en una variable es tan irrelevante como el nombre de la variable o el espacio después del =.
jalf
12

No es para repetir lo que todos ya han dicho, pero tenga a mano la siguiente hoja de trucos para manipulaciones de archivos:

  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);
Vivek
fuente
6

Todas estas respuestas con .ReadAllBytes(). Otra pregunta similar (no diré duplicada, ya que estaban tratando de refactorizar su código) se hizo en SO aquí: ¿La mejor manera de leer un archivo grande en una matriz de bytes en C #?

Se hizo un comentario en una de las publicaciones con respecto a .ReadAllBytes():

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

Un mejor enfoque, para mí, sería algo como esto, con 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;
}

Pero ese soy solo yo ...

Por supuesto, todo esto supone que tiene la memoria para manejarlo byte[]una vez que se lee, y no puse la File.Existsverificación para asegurarme de que el archivo esté allí antes de continuar, ya que lo haría antes de llamar a este código.

vapcguy
fuente
1
Hay un error en su código, no necesita el nuevo en la declaración de uso que debe usar (FileStream fs = File.OpenRead (fileName)
JoseR
No es tanto un error (creo que el código aún se compilaría) pero lo eliminé de todos modos. Buena atrapada.
vapcguy
3

se ve lo suficientemente bien como una versión genérica. Puede modificarlo para satisfacer sus necesidades, si son lo suficientemente específicas.

también pruebe las excepciones y condiciones de error, como que el archivo no existe o no se puede leer, etc.

también puede hacer lo siguiente para ahorrar espacio:

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

Otros han notado que puede usar el archivo File.ReadAllBytes. El método incorporado está bien, pero vale la pena señalar que el código que publica arriba es frágil por dos razones:

  1. Streames IDisposable: debe colocar la FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)inicialización en una cláusula using para asegurarse de que el archivo esté cerrado. No hacer esto puede significar que la transmisión permanece abierta si ocurre una falla, lo que significará que el archivo permanecerá bloqueado, y eso puede causar otros problemas más adelante.
  2. fs.Readpuede leer menos bytes de los que solicita. En general, el .Readmétodo de una Streaminstancia leerá al menos un byte, pero no necesariamente todos los bytes que solicite. Deberá escribir un bucle que vuelva a intentar leer hasta que se lean todos los bytes. Esta página explica esto con más detalle.
Eamon Nerbonne
fuente