2017-10-18 8 views
1

Comment remplacer le contenu d'un ZipArchiveEntry? code suivant à l'aide StreamWriter avec StringBuilder échoue si le nouveau contenu de fichiers sont plus courts que ceux d'origine, par exemple:Écraser le contenu de 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" 
    } 
} 

fichier contenant Produit nouveaux et anciens contenus mélangés « baz123123 » au lieu de prévu « baz123 ». Existe-t-il un moyen de jeter l'ancien contenu de ZipArchiveEntry avant d'écrire les nouveaux?
note: Je ne veux pas extrait le fichier, je voudrais changer le contenu de l'archive.

+0

(Vous avez besoin de l'archive "Test.zip" avec le fichier foo.txt, je ne peux vraiment pas l'attacher à la question, mais en faire une devrait être assez rapide) – wondra

+0

Merci @wondra de mettre à jour le code pour créer le https://stackoverflow.com/help/mcve. – mjwills

+0

@wondra récupérer le contenu, supprimer l'entrée, modifier le contenu, ajouter une entrée avec le contenu modifié. – Nkosi

Répondre

1

La mise à jour de l'archive signifie que vous ajoutez, déplacez ou supprimez une entrée de l'archive.

Envisagez de suivre les étapes suivantes.

  • Obtenez le contenu d'entrée

  • Supprimez l'entrée de l'archive (prendre note du nom/lieu)

  • Modifier le contenu comme souhaité.

  • Ajouter du contenu modifié à l'archive.

+0

La fonction 'set.Open()' du flux 'SetLength (document.Length)' fonctionne également. Une surcharge avec 'bool append' ne serait pas moins bienvenue si l'API devait être compatible avec' Stream's. – wondra

+1

@wondra vous devriez envisager d'ajouter cette information comme une réponse personnelle pour aider les autres qui pourraient avoir le même problème dans le futur. – Nkosi

+0

@wondra Je pense que vous ne devriez pas accepter ma réponse et accepter votre réponse personnelle car je crois que vous répondez est l'option la plus logique. Je vais supprimer ma réponse. – Nkosi

3

Une alternative consiste à SetLength(document.Length) du courant entry.Open().

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

Le code ci-dessous maintient la structure de votre code de base, mais supprime explicitement et recrée le fichier pour faire en sorte que les données « restes » ne restent pas. @mjwills juste ctrl + c et ctrl + v le code et appuyez sur Exécuter

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); 
    } 
}