¿Cómo puedo leer / transmitir un archivo sin cargar todo el archivo en la memoria?

¿Cómo puedo leer un archivo arbitrario y procesarlo “pieza por pieza” (es decir, byte por byte o algún otro tamaño de fragmento que ofrezca el mejor rendimiento de lectura) sin cargar todo el archivo en la memoria? Un ejemplo de procesamiento sería generar un hash MD5 del archivo, aunque la respuesta podría aplicarse a cualquier operación.

Me gustaría tener o escribir esto, pero si consigo el código existente también sería genial.

(do#)

Aquí hay un ejemplo de cómo leer un archivo en fragmentos de 1 KB sin cargar todo el contenido en la memoria:

 const int chunkSize = 1024; // read the file by chunks of 1KB using (var file = File.OpenRead("foo.dat")) { int bytesRead; var buffer = new byte[chunkSize]; while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0) { // TODO: Process bytesRead number of bytes from the buffer // not the entire buffer as the size of the buffer is 1KB // whereas the actual number of bytes that are read are // stored in the bytesRead integer. } } 

System.IO.FileStream no carga el archivo en la memoria.
Esta secuencia es buscable y el algoritmo de hash MD5 no tiene que cargar la memoria intro de la secuencia (archivo) tampoco.

Reemplace file_path con la ruta a su archivo.

 byte[] hash = null; using (var file = new FileStream(file_path, FileMode.Open)) { using (var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider()) { hash = md5.ComputeHash(stream); } } 

Aquí, su Hash MD5 se almacenará en la variable hash .

  int fullfilesize = 0;// full size of file int DefaultReadValue = 10485760; //read 10 mb at a time int toRead = 10485760; int position =0; // int // byte[] ByteReadFirst = new byte[10485760]; private void Button_Click(object sender, RoutedEventArgs e) { using (var fs = new FileStream(@"filepath", FileMode.Open, FileAccess.Read)) { using (MemoryStream requestStream = new MemoryStream()) { fs.Position = position; if (fs.Position >= fullfilesize) { MessageBox.Show(" all done"); return; } System.Diagnostics.Debug.WriteLine("file position" + fs.Position); if (fullfilesize-position < toRead) { toRead = fullfilesize - position; MessageBox.Show("last time"); } System.Diagnostics.Debug.WriteLine("toread" + toRead); int bytesRead; byte[] buffer = new byte[toRead]; int offset = 0; position += toRead; while (toRead > 0 && (bytesRead = fs.Read(buffer, offset, toRead)) > 0) { toRead -= bytesRead; offset += bytesRead; } toRead = DefaultReadValue; } } } 

Copiando Darin’s, este método leerá 10mb de fragmentos hasta el final del archivo

 const int MAX_BUFFER = 1024; byte[] Buffer = new byte[MAX_BUFFER]; int BytesRead; using (System.IO.FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) while ((BytesRead = fileStream.Read(Buffer, 0, MAX_BUFFER)) != 0) { // Process this chunk starting from offset 0 // and continuing for bytesRead bytes! } 
 const long numberOfBytesToReadPerChunk = 1000;//1KB using (BinaryReader fileData = new BinaryReader(File.OpenRead(aFullFilePath)) while (fileData.BaseStream.Position - fileData.BaseStream.Length > 0) DoSomethingWithAChunkOfBytes(fileData.ReadBytes(numberOfBytesToReadPerChunk)); 

Como entiendo las funciones utilizadas aquí (específicamente BinaryReader.ReadBytes ), no hay necesidad de seguir cuántos bytes ha leído. Solo necesita saber la longitud y la posición actual del ciclo while, que la secuencia le dice.