2016-09-15 110 views
2

我正在編寫database備份功能,從System.Diagnostics.Process object,從StandardOutput (StreamReader)屬性讀取。我已成功寫入純文件。C#緩衝GZipStream壓縮

//This code successfully wrote text files. 
StreamWriter f = new StreamWriter(BackupPath); 
while (true) { 
    //RaiseProgressedEvent(new DBProgressEventArgs(dbsize, progress, "Writing backup file")); 

    int buffsize = 512; 
    char[] buff = new char[buffsize]; 
    int count = p.StandardOutput.ReadBlock(buff, 0, buff.Length); 
    if (count == 0) break; 
    // If no more data, trim the char array 
    if (p.StandardOutput.Peek() < 0) buff = (from c in buff where c > 0 select c).ToArray(); 

    f.Write(buff, 0, count); 
    progress += buffsize; 
} 
f.Close(); 

但是,當我更改爲GZipStream

//This code yields a broken gzip file. 
//*2 lines changed: StreamWriter changed into FileStream. 
FileStream fs = File.Create(BackupPath); 
GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, true); 

while (true) { 
    RaiseProgressedEvent(new DBProgressEventArgs(dbsize, progress, "Writing backup file")); 

    int buffsize = 512; 
    char[] buff = new char[buffsize]; 
    int count = p.StandardOutput.ReadBlock(buff, 0, buff.Length); 
    if (count == 0) break; 
    if (p.StandardOutput.Peek() < 0) buff = (from c in buff where c > 0 select c).ToArray(); 

    //With UTF 8 Encoding, write to gzipstream. 
    //f.write changed into the following 2 lines: 
    Encoding enc = Encoding.UTF8; 
    zipStream.Write(enc.GetBytes(buff), 0, enc.GetByteCount(buff)); 

    progress += buffsize; 
} 
fs.Close(); 

所得GZip文件不完整/斷開。當用7zip進行解壓縮,然後用notepad++打開時,幾乎所有的文本都很好,只有靠近文件末尾的一些字節丟失。我不確定,但也許錯誤是:zipStream.Write(enc.GetBytes(buff), 0, enc.GetByteCount(buff)); 也許與enc.GetByteCount(buff)有關。

讀取緩衝爲多線程,用於處理大文件。那麼......爲什麼最後的字節會丟失?我在哪裏做錯了?

+3

有什麼可疑的是,你從來沒有關閉/處置你的'zipStream'。這可能沒有必要,但這是我第一次嘗試。 – hvd

+0

是的,你正在關閉一些未顯示的'fs',但可能是底層文件流。如果不讓GZipStream完成工作,你無法關閉它。總是關閉最後一個,而不是鏈中的第一個。 –

+0

fs是代碼片段頂部的FileStream。 –

回答

2

試着這麼做:

  • 使用的GZipStream一個構造函數,關閉FileStreamDispose

    using(FileStream fs = File.Create(BackupPath)) 
    using(GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, false)) 
    { 
    
    while (true) { 
        RaiseProgressedEvent(new DBProgressEventArgs(dbsize, progress, "Writing backup file")); 
    
    int buffsize = 512; 
    char[] buff = new char[buffsize]; 
    int count = p.StandardOutput.ReadBlock(buff, 0, buff.Length); 
    if (count == 0) break; 
    if (p.StandardOutput.Peek() < 0) buff = (from c in buff where c > 0 select c).ToArray(); 
    
    //With UTF 8 Encoding, write to gzipstream. 
    //f.write changed into the following 2 lines: 
    Encoding enc = Encoding.UTF8; 
    zipStream.Write(enc.GetBytes(buff), 0, enc.GetByteCount(buff)); 
    
    progress += buffsize; 
    } 
    } 
    
+0

@hvd註釋(關閉zipstream)中包含'FileStream'和'GZipStream'解決了這個問題。但是這個答案也解決了這個問題。不知何故,這個代碼更整潔。謝謝。 –

0

如果你想要的是拉鍊在同一文件夾中的文件,那麼我嘗試下面的代碼正在工作。

private void button1_Click(object sender, EventArgs e) 
    { 

     try 
     { 
      FileInfo fi = new FileInfo(@"F:\Harris\abc.txt"); 
      FileStream fs = File.OpenRead(@"F:\Harris\abc.txt"); 
      using (FileStream compressedFileStream = File.Create(fi.FullName + ".gz")) 
      { 
       using (GZipStream compressionStream = new GZipStream(compressedFileStream, 
       System.IO.Compression.CompressionMode.Compress, true)) 
       { 
        fs.CopyTo(compressionStream); 
       } 
      }//end using 

      MessageBox.Show("Done"); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message); 
     } 
     finally { } 
    }