2017-10-18 131 views
1

如何覆蓋ZipArchiveEntry的內容?繼使用StreamWriterStringBuilder如果新的文件內容比原有的更短的失敗,例如代碼:覆蓋ZipArchiveEntry的內容

using System.IO.Compression; 
//... 
using (var archive = ZipFile.Open("Test.zip", ZipArchiveMode.Update)) 
{ 
    StringBuilder document; 
    var entry = archive.GetEntry("foo.txt");//entry contents "foobar123" 
    using (StreamReader reader = new StreamReader(entry.Open())) 
    { 
     document = new StringBuilder(reader.ReadToEnd()); 
    } 

    document.Replace("foobar", "baz"); //builder contents "baz123" 

    using (StreamWriter writer = new StreamWriter(entry.Open())) 
    { 
     writer.Write(document); //entry contents "baz123123", expected "baz123" 
    } 
} 

產生含有混合了「baz123123」,而不是預期的「baz123」新老內容的文件。 在寫新的內容之前,如何丟棄ZipArchiveEntry的舊內容或許有一種方法?
注意:我不想提取該文件,我想更改內容的存檔。

+0

@mjwills只是按Ctrl + C和Ctrl + V的代碼,然後按運行。 (需要使用foo.txt文件的「Test.zip」壓縮包,但是不能真正將其附加到問題上,但是應該足夠快) – wondra

+0

感謝@wondra更新代碼以使https://stackoverflow.com/help/mcve。 – mjwills

+0

@wondra獲取內容,刪除條目,修改內容,添加修改內容的條目。 – Nkosi

回答

1

更新檔案表示您要添加,移動或從檔案中移除條目。

請考慮執行以下步驟。

  • 獲得進入目錄

  • 刪除從存檔的條目(注意名稱/位置)

  • 修改內容所需。

  • 將修改後的內容添加回存檔。

+0

剛剛發現設置'entry.Open()'流的'SetLength(document.Length)'也可以。如果API與「Stream」一致,那麼使用'bool append'重載將會受到歡迎。 – wondra

+1

@wondra你應該考慮將這些信息作爲自己的答案來幫助未來可能會遇到同樣問題的其他人。 – Nkosi

+0

@wondra我認爲你應該不接受我的答案並接受你的自我回答,因爲我相信你的回答是更合理的選擇。我會刪除我的答案。 – Nkosi

3

替代方案是entry.Open()流的SetLength(document.Length)

using(var stream = entry.Open()) 
{ 
    stream.SetLength(document.Length); 
    using (StreamWriter writer = new StreamWriter(stream)) 
    { 
     writer.Write(document); //entry contents "baz123" 
    } 
} 
1

下面的代碼保存你的基本代碼結構,但明確地刪除並重新創建該文件,以確保「剩餘」數據不會保留。

using (var archive = ZipFile.Open("Test.zip", ZipArchiveMode.Update)) 
{ 
    StringBuilder document; 
    var entry = archive.GetEntry("foo.txt");//entry contents "foobar123" 
    using (StreamReader reader = new StreamReader(entry.Open())) 
    { 
     document = new StringBuilder(reader.ReadToEnd()); 
    } 

    entry.Delete(); 
    entry = archive.CreateEntry("foo.txt"); 
    document.Replace("foobar", "baz"); //builder contents "baz123" 

    using (StreamWriter writer = new StreamWriter(entry.Open())) 
    { 
     writer.Write(document); 
    } 
}