2012-08-27 65 views
2

我在贏取窗體中工作。在執行以下操作時發生錯誤。 它顯示我System.OutOfMemoryException錯誤,當我嘗試連續運行2-3次左右的操作。似乎.NET不能釋放操作中使用的資源。我用於操作的文件相當大,大約在以上,大於500 MB。System.OutofMemoryException在執行GZipStream壓縮時拋出

我的示例代碼如下。請幫助我如何解決錯誤。

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()); 
} 
+2

相反ReadAllBytes',打開源文件',並在循環使用它'Read'方法 –

+0

'ReadAllBytes'是殺手鐗 - 這會讓你的內存超過500MB到 – Reniuz

+0

究竟哪一行導致了OOM異常? – aquinas

回答

5

一個非常粗略的例如可能是

// 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個字節。

+0

是的,但CopyTo更容易。此外,使用更大的緩衝區,如「8 * 1024」。 –

+0

當然你是對的,但我確實認爲阿米特可以自己調整這一點。 @CopyTo thx的提示! –

6

更換ReadAllBytesStream.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); 
    } 
} 
+1

這將自動使用一個明智的緩衝區大小,但是如果你想指定一個緩衝區大小,那麼會有一個CopyTo()重載。 IMO沒有必要讓OP知道它在那裏。默認緩衝區大小僅爲4096. –

0

你可以嘗試使用這種方法來壓縮文件MSDN link

public static void Compress(FileInfo fileToCompress) 
    { 
     using (FileStream originalFileStream = fileToCompress.OpenRead()) 
     { 
      using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz")) 
      { 
       using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress)) 
       { 
         originalFileStream.CopyTo(compressionStream);         
       } 
      } 
     } 
    } 

用法:

string directoryPath = @"c:\users\public\reports"; 

DirectoryInfo directorySelected = new DirectoryInfo(directoryPath); 

foreach (FileInfo fileToCompress in directorySelected.GetFiles()) 
{ 
    Compress(fileToCompress); 
}