2 zip-Dateien zusammenführen

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Translating-IT.

    2 zip-Dateien zusammenführen

    Hallo,

    ich habe mit einem Skript Zip-Dateien aus Ordnern mit n Unterordner erstellen lassen. Das funktioniert auch problemlos, nur kann es vorkommen, dass ich am Ende einige Dateien ähnliche Namen haben, die sich nur durch einen Buchstaben am Ende unterscheiden, (z. B. 2018.zip, 2018a.zip).

    In so einem Fall möchte ich 2018.zip und 2018a.zip automatisiert über eine WPF-Anwendung öffnen und die Dateien von 2018a.zip in 2018.zip zusammenführen. Bestehende Ordner und Dateien sollen überschrieben und 2018a.zip am Ende gelöscht werden. Wie kann ich das lösen? Ich denke mal mit ZipArchive, aber ich finde da nichts wirklich was Zielführendes.

    Alternativ könnte auch statt dem Erstellen der Datei 2018a.zip (wird mithilfe von ZipFile.CreateFromDirectory direkt aus einem Ordner erstellt) der Ordner mit n Unterordnern und entsprechenden Dateien in 2018.zip hinzugefügt werden.

    LG,
    Pascal
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    @Translating-IT Von Zip nach Zip geht wahrscheinlich nicht, Du musst erst eine ZIP entpacken und dann den entpackten Inhalt der bestehenden ZIP hinzufügen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ok, das wäre dann der Weg über die Alternative. Das habe ich auch schon versucht, aber dann habe ich nur den Ordnernamen in der Zip-Datei, aber die Dateien und Unterordner nicht. Oder habe ich einen Befehl übersehen, mit dem ich direkt einen ganzen Ordner samt Unterordner und Dateien hinzufügen kann (im Sinne von ZipFile.CreateFromDirectory)?
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    @Translating-IT Ich dachte, Du hast das Befüllen von Zips im Griff?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany wie schon oben geschrieben, ich erstelle eine zip-Datei direkt aus einem Ordner mit dem oben genannten Befehl. Einzelne Dateien (im Hauptordner) hab ich auch schon geschafft hinzuzufügen, aber keine Ordner bzw. Dateien in Unterordnern. Komischerweise finde ich dazu auch keine Anleitungen. Immer nur wie man eine Datei im Hauptordner hinzufügt.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Ich würde das gleiche empfehlen wie @ErfinderDesRades.
    Entpacke deine beiden Verzeichnisse (A alt / B neu) in deinen TEMP Ordner und kopiere anschließend entsprechend deiner Anforderung (nur neuere Dateien) in dein Verzeichnis A. Anschließend wieder als ZIP verpacken und die TEMP Ordner löschen.
    Da du die Routine ja schon hast ist es ja kein Problem, da du nichts neues schreiben musst, sondern nur auf die Routine nochmals zugreifst.
    Du hast Glück soetwas ähnliches gab es hier erst. Aber das Ziel Archiv dürfte hier vermutlich dennoch erst entpackt werden müssen.

    C#-Quellcode

    1. public static void ZipDirectory(string rootDir, string outputFileName)
    2. {
    3. ZipArchiveMode mode = File.Exists(outputFileName) ? ZipArchiveMode.Update : ZipArchiveMode.Create;
    4. using (ZipArchive archive = ZipFile.Open(outputFileName, mode))
    5. {
    6. foreach (string file in Directory.GetFiles(rootDir, "*.*", SearchOption.AllDirectories))
    7. {
    8. string pathRoot = Path.GetPathRoot(file);
    9. string fileName = file.Replace(pathRoot, ""); // Laufwerksbuchstaben entfernen
    10. archive.CreateEntryFromFile(file, fileName);
    11. }
    12. }
    13. }

    ErfinderDesRades schrieb:

    Na, dann ruf das Script nochmal auf das kann das doch.
    Oder?

    Nur wenn ich einen gesamten Ordner habe, den ich in eine neue Datei packe. Hier habe ich aber entweder 2 zip-Dateien oder 1 zip-Datei und einen Ordner.

    Entpacke deine beiden Verzeichnisse (A alt / B neu) in deinen TEMP Ordner und kopiere anschließend entsprechend deiner Anforderung (nur neuere Dateien) in dein Verzeichnis A. Anschließend wieder als ZIP verpacken und die TEMP Ordner löschen.
    Da du die Routine ja schon hast ist es ja kein Problem, da du nichts neues schreiben musst, sondern nur auf die Routine nochmals zugreifst.


    Ok, damit ergibt die Antwort von ErfinderdesRades mehr Sinn.

    an sich eine gute Idee, nur kann es sein, dass eine bestehende Datei mehrere GB groß ist, und ein Entpacken wollte ich daher verhindern. Statt Temp-Ordner hatte ich daran gedacht, einen Ordner auf dem Laufwerk zu erstellen, wo gezippt wird … aber es muss doch auch mit hinzufügen der Ordner samt Unterordnern gehen oder beide Dateien zusammenzuführen, ohne beide wieder zu entpacken.

    @ThomasG82 Ok, in dem Fall kann ich genausogut alles zuerst entpacken und mit einem kurzen Befehl neu zippen. Ich habe aber am späten Abend einen ähnlichen Ansatz gefunden und wollte morgen im Büro versuchen, den einzubauen bzw. bei dem gefundenen Ansatz womöglich auch die Lösung für das Hinzufügen von Ordnern und Unterordnern gefunden. Ich bin mir aber nicht ganz sicher. Werde mich auf jeden Fall melden, welche Lösung dann für mich funktioniert.

    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Translating-IT“ ()

    Ich hab das grad mal selbst ausprobiert, du musst nichts entpacken. Du öffnest das Archiv das du aktualisieren willst mit ZipArchiveMode.Update danach öffnest du das Archiv das als Quelle dienen soll. Anschließend durchläufst du alle ZipArchiveEntries und öffnest diese, den resultierenden Stream liest du mit einem StreamReader bis zum Ende. Nun erstellst du dir in deinem Zielarchiv einen neuen Eintrag und öffnest diesen ebenfalls. In den daraus resultierendem Stream schreibst du mit einem StreamWriter den Stream des geöffnetem ZipArchiveEntry.

    Beispiel

    C#-Quellcode

    1. public static void MergeZipArchives(string targetArchive, string srcArchive)
    2. {
    3. if (string.IsNullOrEmpty(targetArchive) || string.IsNullOrEmpty(srcArchive))
    4. return;
    5. using (ZipArchive targetZip = ZipFile.Open(targetArchive, ZipArchiveMode.Update))
    6. using (ZipArchive sourceZip = ZipFile.Open(srcArchive, ZipArchiveMode.Read))
    7. {
    8. foreach(ZipArchiveEntry entry in sourceZip.Entries)
    9. {
    10. using (Stream streamSrc = entry.Open())
    11. using (StreamReader sr = new StreamReader(streamSrc))
    12. {
    13. ZipArchiveEntry e = targetZip.CreateEntry(entry.FullName);
    14. using (StreamWriter sw = new StreamWriter(e.Open()))
    15. sw.WriteLine(sr.ReadToEnd());
    16. }
    17. }
    18. }
    19. }

    Das was @Fakiz erwähnt ist auch gut, das hatte ich im Kopf aber nicht gefunden. Da ist nur die Frage ob das letztendlich gut ist da bei der Methode ZipArchiveMode.Update alles reinweg über den RAM läuft. Und so wie du, @Translating-IT, es erwähnst handelt es sich ja um sehr große Dateien. Dies könnte letztlich dann zu einem Break führen weil der Arbeitsspeicher (wenn er zu gering ist) ausgelastet ist. Der Schreib-/Lesevorgang auf einer SSD Festplatte ist da sicherer, m.M.n.
    Hi

    @Translating-IT Du könntest beide ZIPs durchlaufen und eine Diff erstellen. Aus Windowssicht gesehen ist eine ZIP ein "komprimierter" Ordner und wie jeder Ordner kann die Ordnerstruktur und deren Inhalt aufgelistet/durchlaufen werden. Im Prinzip durchläufst beide ZIPs und erstellt auf Platte nocheinmal die gleiche Ordnerstruktur (ab Root abwärst) die nur die Differenzen und Unterschiede (neue "Unter"-Ordner bzw neue Dateien bzw Dateien die sich in der Größe geändert haben) beinhaltet. So stellst Du sicher das nicht die komplette ZIP entpackt werden muss sondern nur das, was sich verändert hat. Die so erstellte Diff-Ordnerstruktur wird dann wieder in die andere ZIP kopiert.
    Mfg -Franky-
    Ok, ich habe es nun so gelöst, dass ich (aufgrund der möglichen Größe der Dateien) die zip-Datei in einen Ordner entpacke, den Inhalt der anderen Datei dann auch dazu gebe und diesen Ordner als gesamtes zippe. Das scheint wirklich das einfachste zu sein. Bei kleineren Dateien wäre wohl auch ein Stream, wie von @Fakiz beschrieben, sehr wohl denkbar.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.
    Dir ist aber klar, wenn du zu wenig Arbeitsspeicher hast, um eine Komprimierte Datei von einer *.zip in eine andere *.zip zu packen kannst du natürlich auch keine *.zip erstellen wenn du die Dateien erst entpackst. Und dann wieder versuchst zu packen.

    Wenn du dir bezüglich der Performance sorgen machst bietet Visual Studio Diagnosetools an auch ProcessExplorer ist ein sehr starkes Werkzeug um die Performance von .Net Anwendungen zu prüfen.
    also mit ZipFile.CreateFromDirectory hat er selbst bei einem Ordner mit 6 GB heute nicht mal 70 MB Ram gebraucht.
    :!: Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.