Pregunta

Tengo un archivo zip que contiene una estructura de carpetas como

  • principal de la carpeta/
    • subFolder1/
    • subFolder2/
    • subFolder3/
      • archivo3.1
      • archivo3.2

Me gustaría cambiar el nombre de la carpeta main-folder para que vamos a decir versionXY dentro de muy archivo zip utilizando Java.

Hay una forma más simple de extraer todo el archivo zip y volver a crear uno nuevo con los nuevos nombres de carpeta?

¿Fue útil?

Solución

Zip es un formato de archivo, por lo que la mutación en general, consiste en reescribir el archivo.

Algunas características particulares de la cremallera también en el camino (zip está lleno de "características").Así como el directorio central al final de los archivos, cada archivo de componente es precedida por su nombre de archivo.Zip no tiene un concepto de directorios: los nombres de archivo son sólo cadenas que suceder para incluir los caracteres " / " (y subcadenas como "../".

Así, usted realmente necesita para copiar el archivo con ZipInputStream y ZipOutputStream, cambiar el nombre de la marcha.Si realmente quería usted podría reescribir el archivo en lugar de hacer su propio búfer.El proceso de la causa de los contenidos a ser recomprimido como la norma API no dispone de medios para la obtención de los datos en un formato comprimido.

Otros consejos

Sé que preguntó acerca de Java, pero sólo para fines de archivo pensé que iba a aportar una nota sobre .NET.

DotNetZip es una biblioteca .NET para archivos zip que permite el cambio de nombre de las entradas. Como afirma la respuesta de Tom Hawtin, directorios no son entidades de primera clase en los metadatos del archivo zip, y como resultado, no hay bibliotecas zip, que yo sepa exponen una "cambiar el nombre de directorio" verbo. Sin embargo, algunas bibliotecas le permiten cambiar el nombre de todas las entradas que tienen nombres que indican un directorio en particular, que le da el resultado que desea.

En DotNetZip, se vería así:

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

También puede agregar o eliminar entradas, dentro de la cláusula de usar.

Si guarda en el mismo archivo, a continuación, vuelve a escribir DotNetZip sólo el cambio de metadatos - las cabeceras de entrada y los registros del directorio centrales para las entradas cambiado el nombre, lo que ahorra tiempo con archivos de gran tamaño. Si guarda en un archivo nuevo o un arroyo, a continuación, todos los datos se escribe postal.

Creo que usted será capaz de encontrar ayuda para esta tarea mediante el Commons Comprimir , especialmente ZipArchiveEntry

Esto está haciendo el truco. Blazing rápido ya que sólo funciona en el directorio central y no los archivos.

//  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();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top