¿La mejor manera de leer un archivo grande en una matriz de bytes en C#?

Resuelto Tony_Henrich asked hace 14 años • 12 respuestas

Tengo un servidor web que leerá archivos binarios grandes (varios megabytes) en matrices de bytes. El servidor podría estar leyendo varios archivos al mismo tiempo (diferentes solicitudes de página), por lo que estoy buscando la forma más optimizada de hacerlo sin sobrecargar demasiado la CPU. ¿El siguiente código es lo suficientemente bueno?

public byte[] FileToByteArray(string fileName)
{
    byte[] buff = null;
    FileStream fs = new FileStream(fileName, 
                                   FileMode.Open, 
                                   FileAccess.Read);
    BinaryReader br = new BinaryReader(fs);
    long numBytes = new FileInfo(fileName).Length;
    buff = br.ReadBytes((int) numBytes);
    return buff;
}
Tony_Henrich avatar Jan 09 '10 04:01 Tony_Henrich
Aceptado

Simplemente reemplace todo con:

return File.ReadAllBytes(fileName);

Sin embargo, si le preocupa el consumo de memoria, no debe leer todo el archivo en la memoria de una sola vez. Deberías hacerlo en trozos.

Mehrdad Afshari avatar Jan 08 '2010 21:01 Mehrdad Afshari

Podría argumentar que la respuesta aquí generalmente es "no". A menos que necesite absolutamente todos los datos a la vez, considere usar una StreamAPI basada en (o alguna variante de lector/iterador). Esto es especialmente importante cuando tiene múltiples operaciones paralelas (como lo sugiere la pregunta) para minimizar la carga del sistema y maximizar el rendimiento.

Por ejemplo, si está transmitiendo datos a una persona que llama:

Stream dest = ...
using(Stream source = File.OpenRead(path)) {
    byte[] buffer = new byte[2048];
    int bytesRead;
    while((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
        dest.Write(buffer, 0, bytesRead);
    }
}
Marc Gravell avatar Jan 08 '2010 21:01 Marc Gravell

Yo pensaría esto:

byte[] file = System.IO.File.ReadAllBytes(fileName);
Powerlord avatar Jan 08 '2010 21:01 Powerlord

Su código se puede factorizar con esto (en lugar de File.ReadAllBytes):

public byte[] ReadAllBytes(string fileName)
{
    byte[] buffer = null;
    using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
    {
        buffer = new byte[fs.Length];
        fs.Read(buffer, 0, (int)fs.Length);
    }
    return buffer;
} 

Tenga en cuenta la limitación de tamaño de archivo Integer.MaxValue impuesta por el método de lectura. En otras palabras, sólo puedes leer un fragmento de 2 GB a la vez.

Tenga en cuenta también que el último argumento de FileStream es el tamaño del búfer.

También sugeriría leer sobre FileStream y BufferedStream .

Como siempre, un programa de muestra simple para perfilar cuál es el más rápido será el más beneficioso.

Además, su hardware subyacente tendrá un gran efecto en el rendimiento. ¿Está utilizando unidades de disco duro basadas en servidor con cachés grandes y una tarjeta RAID con memoria caché integrada? ¿O estás utilizando una unidad estándar conectada al puerto IDE?

 avatar Jan 08 '2010 21:01