Question

J'ai un fichier zip contenant une structure de dossiers comme

  • principal dossier /
    • SubFolder1 /
    • dossier2 /
    • subFolder3 /
      • file3.1
      • file3.2

Je voudrais renommer le dossier à main-folder disons dans ce fichier versionXY zip très en utilisant Java.

Y at-il un moyen plus simple que d'extraire tout le fichier zip et de recréer une nouvelle en utilisant les nouveaux noms de dossier?

Était-ce utile?

La solution

Zip est un format d'archive, donc implique généralement muter la réécriture du fichier.

Quelques caractéristiques particulières de zip également prendre le chemin (zip est pleine de « caractéristiques »). Ainsi que le répertoire central à la fin de l'archive, chaque fichier composant est précédé par son nom de fichier. Zip ne dispose pas d'un concept de répertoires - noms de fichiers ne sont que des chaînes qui arrivent à inclure des caractères « / » (et des sous-chaînes telles que » ../".

Alors, vous avez vraiment besoin de copier le fichier en utilisant et ZipInputStream ZipOutputStream, changement de nom que vous allez. Si vous vous vouliez vraiment pourrait réécrire le fichier en place de faire votre propre tampon. Le procédé ne provoque au contenu d'être recomprimé comme l'API standard n'a aucun moyen d'obtention des données sous forme comprimée.

Autres conseils

Je sais que vous avez demandé à propos de Java, mais seulement à des fins d'archives, je pensais que je contribuerais une note sur .NET.

DotNetZip est une bibliothèque .NET pour les fichiers zip qui permet de renommer des entrées. Comme les états de réponse de Tom Hawtin, les répertoires ne sont pas des entités de première classe dans les métadonnées de fichier zip, et par conséquent, pas de bibliothèques zip que je connais exposer une « renommer le répertoire » verbe. Mais certaines bibliothèques vous permettent de changer le nom de toutes les entrées qui ont des noms qui indiquent un répertoire particulier, ce qui vous donne le résultat que vous voulez.

Dans DotNetZip, il ressemblerait à ceci:

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

Vous pouvez également ajouter ou supprimer des entrées, à l'intérieur de la clause à l'aide.

Si vous enregistrez dans le même fichier, puis DotNetZip réécrit uniquement les métadonnées modifiées - les en-têtes d'entrée et les enregistrements de répertoire central des entrées rebaptisés, qui permet de gagner du temps avec les grandes archives. Si vous enregistrez un nouveau fichier ou d'un ruisseau, puis toutes les données zip sera écrite.

Je pense que vous serez en mesure de trouver de l'aide pour cette tâche en utilisant Commons Compress , en particulier ZipArchiveEntry

fait l'affaire. Ultra-rapide, car il ne fonctionne que sur le répertoire central et non les fichiers.

//  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();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top