Frage

Ich habe eine Zip-Datei eine Ordnerstruktur wie

enthalten
  • main-Ordner /
    • SubFolder1 /
    • Unterordner2 /
    • subFolder3 /
      • File3.1
      • file3.2

würde Ich mag Ordner main-folder umbenennen, um die versionXY im Inneren, die sehr Zip-Datei mit Java sagen zu lassen.

Gibt es einen einfacheren Weg, als die gesamte Zip-Datei extrahieren und einen neuen mit den neuen Ordnernamen neu zu erstellen?

War es hilfreich?

Lösung

Zip ist ein Archivformat, mutiert so allgemein die Datei beinhaltet neu zu schreiben.

Einige Besonderheiten zip erhalten auch in der Art und Weise (zip ist voll von "Features"). Neben dem zentrale Verzeichnis am Ende des Archivs, jede Komponente Datei durch die Dateinamen vorangestellt. Zip hat kein Konzept der Verzeichnisse - Dateinamen sind nur Zeichenfolgen, die enthalten zufällig „/“ Zeichen (und Teil wie“../".

So müssen Sie wirklich die Datei mit ZipInputStream und ZipOutputStream kopieren, umbenennen, wie Sie gehen. Wenn Sie wollte wirklich Sie konnte die Datei anstelle tun, um Ihre eigene Pufferung umschreiben. Das Verfahren bewirkt der Inhalt als der Standard-API keine Mittel zur Gewinnung der Daten in komprimierter Form aufweist rekomprimiert werden.

Andere Tipps

Ich weiß, fragte man über Java, aber nur für Archivierungszwecke Ich dachte, ich eine Notiz für .NET beitragen würde.

DotNetZip ist eine .NET-Bibliothek für Zip-Dateien, die Umbenennung von Einträgen ermöglicht. Als Tom Hawtin Antwort Staaten, sind Verzeichnisse nicht erstklassige Einrichtungen in den Zip-Datei-Metadaten und als Ergebnis keine Zip-Bibliotheken, die ich kenne ein „Verzeichnis umbenennen“ Verb aussetzen. Aber einige Bibliotheken können Sie alle Einträge umbenennen, die Namen haben, die ein bestimmtes Verzeichnis angeben, unter der Sie das Ergebnis erhalten Sie wollen.

In DotNetZip, es würde wie folgt aussehen:

 var regex = new Regex("/OldDirName/.*$");
 int renameCount= 0;
 using (ZipFile zip = ZipFile.Read(ExistingZipFile))
 {
    foreach (ZipEntry e in zip)
    {
        if (regex.IsMatch(e.FileName))
        {
            // rename here
            e.FileName = e.FileName.Replace("/OldDirName/", "/NewDirName/");
            renameCount++;
        }
    }
    if (renameCount > 0)
    {
        zip.Comment = String.Format("This archive has been modified. {0} entries have been renamed.", renameCount);
        // any changes to the entries are made permanent by Save()
        zip.Save();  // could also save to a new zip file here
    }
 }

Sie können auch Einträge hinzufügen oder entfernen, in der using-Klausel.

Wenn Sie auf die gleiche Datei speichern, dann schreibt DotNetZip nur den geänderten Metadaten - den Eintrag Header und die zentralen Verzeichniseinträge für umbenannte Einträge, die Zeit mit großen Archiven spart. Wenn Sie in eine neue Datei oder einen Stream speichern, dann wird der gesamte ZIP-Daten geschrieben.

Ich glaube, Sie werden in der Lage sein, Hilfe für diese Aufgabe zu finden, mit dem Commons Compress , insbesondere ZipArchiveEntry

Das tut den Trick. Blazing schnell, da es nur auf dem zentralen Verzeichnis und die Dateien nicht funktioniert.

//  rezip( zipfile, "/main-folder", "/versionXY" );

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;


protected void rezip( String zipfile, String olddir, String newdir ) {

    Path zipFilePath = Paths.get( zipfile );
    try (FileSystem fs = FileSystems.newFileSystem( zipFilePath, null )) {
        Path oldpathInsideZipPath = fs.getPath( olddir );
        if( ! Files.exists( Paths.get( newdir ) ) )
            Files.createDirectory( Paths.get( newdir ) );

        if ( Files.exists( oldpathInsideZipPath, LinkOption.NOFOLLOW_LINKS ) ) {
            Files.walkFileTree(oldpathInsideZipPath, new SimpleFileVisitor<Path>() {
                 @Override
                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                     throws IOException
                 {
                     if( file.toString().indexOf( olddir ) > -1 ){
                         String a = file.toString().replaceAll( olddir, newdir );
                         Path b = fs.getPath( a );
                         if( ! Files.exists( b.getParent() ) ){
                             Files.createDirectories( b.getParent() );
                         }
                         Files.move( file, b, LinkOption.NOFOLLOW_LINKS );
                     }
                     return FileVisitResult.CONTINUE;
                 }
                 @Override
                 public FileVisitResult postVisitDirectory(Path dir, IOException e)
                     throws IOException
                 {
                     if (e == null) {
                         Files.delete(dir);
                         return FileVisitResult.CONTINUE;
                     } else {
                         // directory iteration failed
                         throw e;
                     }
                 }
             });
        }
        fs.close();
    } catch ( Exception e ) {
        e.printStackTrace();
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top