Se nos presentó la necesidad de añadir contenido a ciertos ficheros ZIP preexistentes, para abordar el problema podíamos usar la librería Commons Compress de Apache (https://commons.apache.org/proper/commons-compress/) o directamente las clases del paquete 'java.util.zip' del JDK.
El problema es que ambas librerías no añaden contenido a un zip preexistente, sino que sobrescriben el contenido del ZIP original por el nuevo contenido. Debe ser por alguna cuestión 'conceptual' relativa al formato ZIP.
Por tanto la forma de abordar el problema es generar un nuevo fichero zip temopral, volcar en dicho fichero el contenido del fichero zip original, añadir al fichero zip temporal el nuevo fichero, borrar el fichero zip original y renombrar el fichero temporal con el nombre del original.
Ya puestos a documentar el tema, dejo el código con la clase generada:
package org.casa.test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class TestZip { private static final int BUFFER_SIZE = 1024; /** * Crea un fichero zip a partir del fichero recibido con el nombre * de dicho fichero y extensión zip, el zip se genera en la carpeta * que contiene el fichero recibido. * * @param fichero * @throws IOException */ public static void comprimeFichero(final File fichero) throws IOException { //Generamos un fichero zip con nombre del fichero recibido y extensión zip final String nombreFichZip = fichero.getName().substring(0, fichero.getName().lastIndexOf("."))+".zip"; //Creamos el nuevo fichero zip en la ubicación del fichero recibido final File zf = new File(fichero.getParentFile()+File.separator+nombreFichZip); final FileOutputStream fos = new FileOutputStream(zf); final ZipOutputStream zos = new ZipOutputStream(fos); //Comprimimos el fichero recibido en el nuevo zip final ZipEntry ze = new ZipEntry(fichero.getName()); zos.putNextEntry(ze); final FileInputStream fisEntry = new FileInputStream(fichero); copyToZip(fisEntry, zos); //Cerramos los manejadores fisEntry.close(); zos.flush(); zos.closeEntry(); zos.close(); fos.close(); } /** * Crea un fichero zip con todos los ficheros contenidos en la carpeta * recibida, el zip tendrá el nombre del directorio con extensión zip y * se ubicará en el directorio padre del directorio recibido. * * @param directorio * @throws IOException */ public static void comprimeDirectorio(final File carpeta) throws IOException { //Generamos un fichero zip con nombre de la carpeta recibida y extensión zip final String nombreFichZip = carpeta.getName()+".zip"; //Creamos el nuevo fichero zip en la carpeta padre de la carpeta recibida final File zf = new File(carpeta.getParentFile()+File.separator+nombreFichZip); final FileOutputStream fos = new FileOutputStream(zf); final ZipOutputStream zos = new ZipOutputStream(fos); //Comprimimos cada fichero de la carpeta en el nuevo zip ZipEntry ze = null; FileInputStream fisEntry = null; for (final File fich : carpeta.listFiles()) { ze = new ZipEntry(fich.getName()); zos.putNextEntry(ze); fisEntry = new FileInputStream(fich); copyToZip(fisEntry, zos); fisEntry.close(); } //Cerramos los manejadores zos.flush(); zos.closeEntry(); zos.close(); fos.close(); } /** * Añade un nuevo fichero comprimido al fichero zip recibido por parámetro. * * Creamos un zip temporal intermedio donde copiamos el contenido del zip * recibido y en este zip temporal añadimos el fichero recibido. Finalmente * reemplazamos el fichero zip original con el fichero zip generado. * * @param zipFile * @param fichero * @throws IOException */ public static void addFicheroZip(final File zipFile, final File fichero) throws IOException { //Guardamos el nombre y el path del fichero zip recibido final String nombreFicheroZip = zipFile.getName(); final String pathFicheroZip = zipFile.getParent(); //Creamos un nuevo fichero zip temporal en la ubicación del zip recibido final File ftemp = File.createTempFile(nombreFicheroZip,null,zipFile.getParentFile()); final FileOutputStream fostemp = new FileOutputStream(ftemp); final ZipOutputStream zostemp = new ZipOutputStream(fostemp); //Abrimos el fichero zip recibido por parametro final FileInputStream fis = new FileInputStream(zipFile); final ZipInputStream zis = new ZipInputStream(fis); //Sacammos el contenido del zip recibido por parametro y lo volcamos al zip temporal ZipEntry ze = zis.getNextEntry(); while (ze!= null) { ze.getName(); zostemp.putNextEntry(ze); copyToZip(zis, zostemp); ze = zis.getNextEntry(); } //Añadimos el fichero nuevo al fichero zip temporal final ZipEntry zenuevo = new ZipEntry(fichero.getName()); zostemp.putNextEntry(zenuevo); final FileInputStream fisNuevo = new FileInputStream(fichero); copyToZip(fisNuevo, zostemp); //Cerramos los manejadores fisNuevo.close(); zis.close(); fis.close(); zostemp.flush(); zostemp.closeEntry(); zostemp.close(); fostemp.close(); //Borramos el fichero zip recibido zipFile.delete(); //Renombramos el fichero temporal nuevo ftemp.renameTo(new File(pathFicheroZip+File.separator+nombreFicheroZip)); } /** * Extrae el contenido del zip recibido por parámetro en la carpeta * que contiene el fichero zip recibido. * * * @param zipFile * @throws IOException */ public static void descomprimeZip(final File zipFile) throws IOException { //Abrimos el fichero zip recibido por parametro final FileInputStream fis = new FileInputStream(zipFile); final ZipInputStream zis = new ZipInputStream(fis); //Extraemos cada fichero del zip en la carpeta del ZIP recibido File fe = null; FileOutputStream fose = null; ZipEntry ze = zis.getNextEntry(); while (ze!= null) { //Procesamos cada fichero del zip fe = new File(zipFile.getParentFile().getCanonicalPath()+File.separator+ze.getName()); fose = new FileOutputStream(fe); copyFromZip(zis, fose); fose.flush(); fose.close(); //Saltamos al siguiente fichero del zip ze = zis.getNextEntry(); } //Cerramos los manejadores zis.close(); fis.close(); } private static void copyToZip(final InputStream is, final ZipOutputStream zos) throws IOException { byte[] buffer = new byte[BUFFER_SIZE]; int length; while ((length = is.read(buffer)) >= 0) { zos.write(buffer, 0, length); } } private static void copyFromZip(final ZipInputStream zis, final OutputStream os) throws IOException { byte[] buffer = new byte[BUFFER_SIZE]; int length; while ((length = zis.read(buffer)) >= 0) { os.write(buffer, 0, length); } } }
Un saludo
No hay comentarios:
Publicar un comentario