2016-03-31 40 views
5

Sto cercando di modificare un file XmlDocument contenuto in un file zip:Modifica ZipArchive in memoria .NET

var zip = new ZipArchive(myZipFileInMemoryStream, ZipArchiveMode.Update); 
var entry = zip.GetEntry("filenameToEdit"); 
using (var st = entry.Open()) 
{ 
    var xml = new XmlDocument(); 
    xml.Load(st); 
    foreach (XmlElement el in xml.GetElementsByTagName("Relationship")) 
    { 
     if(el.HasAttribute("Target") && el.GetAttribute("Target").Contains(".dat")){ 
      el.SetAttribute("Target", path); 
     } 
    } 
    xml.Save(st); 
} 

Dopo l'esecuzione di questo codice il file contenuto non viene modificato. Se invece di xml.Save(st); scrivo l'xml su disco, ho ottenuto quello modificato.

Perché il file modificato non è stato scritto sullo zip? Come lo aggiusto?

EDIT:

ho aggiornato il codice:

var tmp = new MemoryStream(); 
using (var zip = new ZipArchive(template, ZipArchiveMode.Read, true)) 
{ 
    var entry = zip.GetEntry("xml"); 
    using (var st = entry.Open()) 
    { 
     var xml = new XmlDocument(); 
     xml.Load(st); 
     foreach (XmlElement el in xml.GetElementsByTagName("Relationship")) 
     { 
      if (el.HasAttribute("Target") && el.GetAttribute("Target").Contains(".dat")) 
      { 
       el.SetAttribute("Target", path); 
      } 
     } 
     xml.Save(tmp); 
    } 
} 
using (var zip = new ZipArchive(template, ZipArchiveMode.Update, true)) 
{ 
    var entry = zip.GetEntry("xml"); 
    using (var st = entry.Open()) 
    { 
     tmp.Position = 0; 
     tmp.CopyTo(st); 
    } 
} 

In questo modo il file zip viene modificato, ma è funziona solo se la lunghezza dei corsi d'acqua è uguale. Se tmp è più breve il resto del st è ancora nel file ...

Suggerimenti?

+0

Non vedo che si sta salvando la zip ovunque :) – Luaan

+0

Ho saltato la parte di salvare 'myZipFileInMemoryStream' su disco. Non dovrebbe essere inclusa la parte modificata nello stream? – Emaborsa

+0

Apparentemente, dovrebbe - 'Dopo aver recuperato lo stream, puoi leggere o scrivere nello stream. Quando scrivi sullo stream, le modifiche apportate alla voce verranno visualizzate nell'archivio zip. (MSDN). Ma devi anche riavvolgere il flusso - 'st.Position = 0', altrimenti stai semplicemente aggiungendo il nuovo XML alla fine di quello vecchio. Potrebbe essere il problema? :) – Luaan

risposta

0

Io uso questo codice per creare un InMemory Zip (utilizzando la libreria DotNetZip):

 MemoryStream saveStream = new MemoryStream(); 

     ZipFile arrangeZipFile = new ZipFile(); 
     arrangeZipFile.AddEntry("test.xml", "content..."); 
     arrangeZipFile.Save(saveStream); 

     saveStream.Seek(0, SeekOrigin.Begin); 
     saveStream.Flush(); // might be useless, because it's in memory... 

Dopo che ho uno Zip valida all'interno della MemoryStream. Non sono sicuro del motivo per cui ho aggiunto Flush() - direi che questo è ridondante.

Per modificare un Zip esistente è possibile leggerlo in un MemoryStream e invece di creare "nuovo ZipFile()" utilizzare "nuovo ZipFile (byteArray ...)".

+0

Funziona anche se esiste alesty 'test.xml'? Cosa succede se voglio mettere il file in una sottocartella? A cosa serve il 'contenuto? – Emaborsa

+0

arrangeZipFile.AddEntry ("test.xml", "content ..."); => Creerà un nuovo file "text.xml" all'interno del file zip, che è archiviato in memoria, con il contenuto specificato. Se si desidera aggiornare una voce, utilizzare semplicemente il metodo UpdateEntry. Per le sottocartelle: almeno DotNetZip utilizzerà semplicemente il percorso specificato, ad es. se vuoi creare una sottocartella basta chiamarlo in questo modo: AddEntry ("sottocartella/test.xml" ..) –