2011-05-24 38 views
0

我試圖用dotnetzip使用下面的方法來存儲XML文件壓縮成zip文本/ XML文件時:在使用此方法Dotnetzip狀態不好誤差提取

private void writeHosts() 
    { 
     XmlRootAttribute root = new XmlRootAttribute(ROOTNAME_HOST); 
     XmlSerializer ser = new XmlSerializer(typeof(Host[]), root); 
     MemoryStream ms = new MemoryStream(); 
     StreamWriter swriter = new StreamWriter(ms); 

     //write xml to memory stream 
     ser.Serialize(swriter, m_hostList.ToArray()); 
     swriter.Flush(); 

     //be kind, rewind (the stream) 
     ms.Seek(0, SeekOrigin.Begin); 

     //copy memory stream to zip as a file. 
     using (m_repo) 
     { 
      ZipEntry e = m_repo.AddEntry(FILENAME_HOST, ms); 
      e.IsText = true; 
      m_repo.Save(); 
     } 

     swriter.Close(); 
    } 

我再讀取XML文件重新:

private List<Host> readHosts() 
    { 
     XmlRootAttribute root = new XmlRootAttribute(ROOTNAME_HOST); 
     XmlSerializer ser = new XmlSerializer(typeof(Host[]), root); 
     MemoryStream ms = new MemoryStream(); 
     StreamReader reader = new StreamReader(ms); 
     List<Host> retlist = new List<Host>(); 

     //get the vuln list from the zip and read into memory 
     using (m_repo) 
     { 
      ZipEntry e = m_repo[FILENAME_HOST]; 
      e.Extract(ms); 
     } 

     //rewind to the start of the stream 
     ms.Flush(); 
     ms.Seek(0, SeekOrigin.Begin); 

     //Pull the host list from XML 
     Host[] ret = (Host[])ser.Deserialize(reader); 
     retlist.AddRange(ret); 

     ms.Close(); 

     return retlist; 
    } 

然而,此方法將拋出ZlibException - 壞狀態(無效存儲塊長度) - 在e.Extract(MS)呼叫。我已經閱讀了足夠的文檔和示例以確保它可以正常工作,但這也是我第一次使用dotnetzip,因此......有關如何解決此問題的任何想法?

回答

0

我真的不明白你在做什麼,我沒有看到如何創建m_repo,在zip創建階段。看起來它太複雜了。拉鍊提取部分也是同樣的東西。 您可能以某種奇怪的方式創建了zip,這會導致解壓縮錯誤。我不知道,因爲代碼不是全部。

我認爲如果你簡化,你可能會避免這些問題。

假設一個數據傳輸對象類是這樣的:

public class Scrilla 
{ 
    // the parts that get serialized: 
    [XmlElement] 
    public String Name { get;set; } 
    [XmlElement] 
    public DateTime FirstReport { get;set; } 
    [XmlElement] 
    public String MoreInfo { get;set; } 
} 

該代碼將創建一個壓縮文件(保存到一個流),與存儲在ZIP文件作爲條目事情XML表示:

var FILENAME_HOST = "self.xml"; 
    XmlRootAttribute root = new XmlRootAttribute("root"); 
    XmlSerializer ser = new XmlSerializer(typeof(Scrilla), root); 
    MemoryStream zipStream = new MemoryStream(); 
    var scrilla = new Scrilla 
    { 
     Name = "Foop", 
     FirstReport = DateTime.Now, 
     MoreInfo = "see http://example.org" 
    }; 

    // zip up: 
    using (var zip1 = new ZipFile()) 
    { 
     zip1.AddEntry(FILENAME_HOST,(entryName,stream) => { 
       using (var swriter = new StreamWriter(stream)) 
       { 
        ser.Serialize(swriter, scrilla); 
       }}); 
     zip1.Save(zipStream); 
    } 

    // the content (an XML file) is now held in the MemoryStream 
    zipStream.Seek(0, SeekOrigin.Begin); 

如果再想從相同的內存流進行解包,你可以這樣做:

Scrilla unpacked; 
    // unzip: 
    using (var zip2 = ZipFile.Read(zipStream)) 
    { 
     Stream s = zip2[FILENAME_HOST].OpenReader(); 
     unpacked = (Scrilla) ser.Deserialize(new StreamReader(s)); 
    } 

然後證明它的工作:

// prove that it worked - print out to Console 
    var xmlws = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true }; 
    using (var w2 = System.Xml.XmlWriter.Create(Console.Out, xmlws)) 
    { 
     ser.Serialize(w2, unpacked); 
    } 

在創作上面的代碼使用the ZipFile.AddEntry overload that accepts a WriteDelegate。 WriteDelegate是一個函數,在ZipFile.Save()上調用條目名稱和一個流,您應該爲該條目寫入內容。查看DotNetZip文檔以獲取詳細信息。正如你所看到的,這個WriteDelegate只是將一個對象串行化爲一個包裹在該流中的Streamwriter。

拆包還採取了一個快捷方式 - 它只是從可讀流中讀取。

在每種情況下,您都不需要創建和查找額外的內存流。

此代碼適用於我。

如果這對你沒有幫助,也許你可以提供一些更多的細節。

+0

感謝您的建議。我會給他們一個鏡頭,看看是否有幫助。作爲參考,這是我如何創建拉鍊...... 當創建一個新的實例: 'm_repo =新的ZipFile(文件名);' 當在現有拉鍊閱讀: 'm_repo = ZipFile.Read (文件名);' – mcscrilla 2011-05-25 14:12:51