Domanda

Ho un file zip contenente una struttura di cartelle come

  • main-cartella /
    • SubFolder1 /
    • SubFolder2 /
    • subFolder3 /
      • file3.1
      • file3.2

Vorrei rinominare la cartella main-folder al diciamo versionXY dentro quel file utilizzando Java zip.

C'è un modo più semplice di estrarre l'intero file zip e ricreare uno nuovo utilizzando i nuovi nomi delle cartelle?

È stato utile?

Soluzione

Zip è un formato di archivio, in modo da mutare in genere comporta la riscrittura del file.

Alcuni particolari caratteristiche di zip ottengono anche nel modo (zip è piena di "caratteristiche"). Così come la directory centrale alla fine dell'archivio, ogni file componente è preceduto dal nome del file. Zip non ha un concetto di directory - i nomi dei file sono solo le stringhe che capita di includere "/" personaggi (e stringhe, come" ../".

Quindi, si ha realmente bisogno di copiare il file usando ZipInputStream e ZipOutputStream, rinominare, come si va. Se si voleva davvero a voi potrebbe riscrivere il file al suo posto facendo il proprio buffering. Il processo non causare i contenuti da ricompresso come API standard ha alcun mezzo per ottenere i dati in forma compressa.

Altri suggerimenti

So che hai chiesto di Java, ma solo a scopo di archiviazione ho pensato di contribuire con una nota su .NET.

DotNetZip è una libreria .NET per i file zip che consente la ridenominazione di voci. Come afferma risposta di Tom Hawtin, directory non sono entità di prima classe nei metadati del file zip, e, di conseguenza, nessuna libreria zip che so di esporre un "rinominare directory" verbo. Ma alcune librerie permettono di rinominare tutte le voci che hanno i nomi che indicano una particolare directory, che vi dà il risultato desiderato.

In DotNetZip, sarebbe simile a questa:

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

È inoltre possibile aggiungere o rimuovere elementi, all'interno della clausola di utilizzo.

Se si salva sullo stesso file, quindi DotNetZip riscrive solo il mutato metadati - le intestazioni di ingresso e le annotazioni di directory centrale per le voci rinominati, che consente di risparmiare tempo con grandi archivi. Se si salva un nuovo file o un flusso, allora tutti i dati zip ottiene scritti.

Credo che sarete in grado di trovare aiuto per questo compito utilizzando il Commons Compress , soprattutto ZipArchiveEntry

Questo sta facendo il trucco. Velocissimo dato che funziona solo sulla directory centrale e non i file.

//  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();
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top