Как я могу читать / передавать файл без загрузки всего файла в память? - PullRequest
15 голосов
/ 29 июля 2011

Как я могу прочитать произвольный файл и обработать его «кусочек за кусочком» (то есть, побайтный байт или какой-то другой размер фрагмента, который обеспечит наилучшую производительность чтения) без загрузки всего файла в память?Примером обработки может быть создание хеша MD5 файла, хотя ответ может относиться к любой операции.

Я хотел бы иметь или написать это, но если бы я мог получить существующий код, который был бы слишком хорош.

(c #)

Ответы [ 5 ]

23 голосов
/ 29 июля 2011

Вот пример того, как прочитать файл кусками по 1 КБ без загрузки всего содержимого в память:

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.
    }
}
10 голосов
/ 29 июля 2011

System.IO.FileStream не загружает файл в память.
Этот поток является доступным для поиска, и алгоритм хеширования MD5 также не должен загружать внутреннюю память потока (файла).

Пожалуйста, замените file_path на путь к вашему файлу.

byte[] hash = null;

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

Здесь хэш MD5 будет храниться в переменной hash.

4 голосов
/ 16 января 2014
   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;


            }
        }
    }

Копируя Darin's, этот метод будет читать 10 МБ чанков до конца файла

2 голосов
/ 29 июля 2011
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!
    }
1 голос
/ 30 июня 2016
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));

Как я понимаю, функции, используемые здесь (в частности, BinaryReader.ReadBytes), нет необходимости отслеживать, сколько байтов вы прочитали. Вам просто нужно знать длину и текущую позицию цикла while - о чем вам говорит поток.

...