Исключение System.OutofMemoryException при выполнении сжатия GZipStream

Я работаю в формах победы. Получение ошибок при выполнении следующей операции. Он показывает мне ошибку System.OutOfMemoryException, когда я пытаюсь запустить операцию 2-3 раза подряд. Кажется, .NET не может освободить ресурсы, используемые в работе. Файл, который я использую для работы, довольно большой, около более 500 МБ.

Мой пример кода, как показано ниже. Пожалуйста, помогите мне, как решить ошибку.

try
{
   using (FileStream target = new FileStream(strCompressedFileName, FileMode.Create, FileAccess.Write))
   using (GZipStream alg = new GZipStream(target, CompressionMode.Compress))
   {
       byte[] data = File.ReadAllBytes(strFileToBeCompressed);
       alg.Write(data, 0, data.Length);
       alg.Flush();
       data = null;
    }
}
catch (Exception ex)
{
    MessageBox.Show(ex.ToString());
}

person amit patel    schedule 27.08.2012    source источник
comment
Вместо ReadAllBytes откройте исходный файл и используйте его метод Read в цикле   -  person L.B    schedule 27.08.2012
comment
ReadAllBytes является убийцей - он получает все ваши более 500 МБ в ОЗУ   -  person Renatas M.    schedule 27.08.2012
comment
Какая именно строка вызывает исключение OOM?   -  person aquinas    schedule 27.08.2012
comment
байт [] данные = File.ReadAllBytes (strFileToBeCompressed); Линия, где приходит OOM   -  person amit patel    schedule 27.08.2012
comment
Принятый ответ на ваш предыдущий вопрос по-прежнему остается верным stackoverflow.com/questions/12038694/   -  person Security Hound    schedule 27.08.2012


Ответы (3)


Очень грубый пример может быть

// destFile - FileStream for destinationFile 
// srcFile - FileStream of sourceFile
using (GZipStream gz = new GZipStream(destFile, CompressionMode.Compress))
{
     byte[] src = new byte[1024];
     int count = sourceFile.Read(src, 0, 1024);
     while (count != 0)
     {
         gz.Write(src, 0, count );
         count = sourceFile.Read(src, 0, 1024);
     }
}
// flush, close, dispose ..

В общем, я изменил ваш ReadAllBytes так, чтобы он читал только фрагменты по 1024 байта.

person Pilgerstorfer Franz    schedule 27.08.2012
comment
Да, но CopyTo проще. Кроме того, используйте буфер большего размера, например 8*1024 . - person Henk Holterman; 27.08.2012
comment
Конечно, ты прав, Хенк, но я думаю, что Амит сможет адаптировать это самостоятельно. @CopyTo спасибо за подсказку! - person Pilgerstorfer Franz; 27.08.2012

Замените ReadAllBytes на Stream.CopyTo.

using (FileStream target = new FileStream(strCompressedFileName, FileMode.Create, FileAccess.Write))
using (GZipStream alg = new GZipStream(target, CompressionMode.Compress))
{
    using (var fileToRead = File.Open(.....))
    {
        fileToRead.CopyTo(alg);
    }
}
person L.B    schedule 27.08.2012
comment
Это будет автоматически использовать разумный размер буфера, но если вы хотите указать размер буфера, для этого есть перегрузка CopyTo(). В этом нет необходимости, IMO, просто сообщите ОП, что он там. Размер буфера по умолчанию всего 4096. - person Matthew Watson; 27.08.2012