Cómo crear un archivo zip en Java

Tengo un archivo de texto dynamic que selecciona el contenido de una base de datos de acuerdo con la consulta del usuario. Tengo que escribir este contenido en un archivo de texto y comprimirlo en una carpeta en un servlet. ¿Cómo debería hacer esto?

Mira este ejemplo:

StringBuilder sb = new StringBuilder(); sb.append("Test String"); File f = new File("d:\\test.zip"); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(f)); ZipEntry e = new ZipEntry("mytext.txt"); out.putNextEntry(e); byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length); out.closeEntry(); out.close(); 

Esto creará un Zip-File ubicado en la raíz de D: llamado ‘test.zip’ que contendrá un solo archivo llamado ‘mytext.txt’. Por supuesto, puede agregar más entradas zip y también especificar un subdirectorio como:

 ZipEntry e = new ZipEntry("folderName/mytext.txt"); 

Puede encontrar más información sobre la compresión con java aquí:

http://www.oracle.com/technetwork/articles/java/compress-1565076.html

Java 7 tiene ZipFileSystem integrado, que se puede usar para crear, escribir y leer archivos desde un archivo zip.

Java Doc: proveedor de ZipFileSystem

 Map env = new HashMap<>(); env.put("create", "true"); URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip"); try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt"); Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt"); // copy a file into the zip file Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); } 

Para escribir un archivo ZIP, usa un ZipOutputStream. Para cada entrada que desee colocar en el archivo ZIP, crea un objeto ZipEntry. Usted pasa el nombre del archivo al constructor ZipEntry; establece los otros parámetros, como la fecha del archivo y el método de descompresión. Puede anular esta configuración si lo desea. Luego, llama al método putNextEntry de ZipOutputStream para comenzar a escribir un nuevo archivo. Envíe los datos del archivo a la secuencia ZIP. Cuando termine, llame a closeEntry. Repita para todos los archivos que desea almacenar. Aquí hay un esqueleto de código:

 FileOutputStream fout = new FileOutputStream("test.zip"); ZipOutputStream zout = new ZipOutputStream(fout); for all files { ZipEntry ze = new ZipEntry(filename); zout.putNextEntry(ze); send data to zout; zout.closeEntry(); } zout.close(); 

Aquí hay un código de ejemplo para comprimir un directorio completo (incluidos subarchivos y subdirectorios), está utilizando la función de árbol de archivos walk de Java NIO.

 import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipCompress { public static void compress(String dirPath) { Path sourceDir = Paths.get(dirPath); String zipFileName = dirPath.concat(".zip"); try { ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFileName)); Files.walkFileTree(sourceDir, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { try { Path targetFile = sourceDir.relativize(file); outputStream.putNextEntry(new ZipEntry(targetFile.toString())); byte[] bytes = Files.readAllBytes(file); outputStream.write(bytes, 0, bytes.length); outputStream.closeEntry(); } catch (IOException e) { e.printStackTrace(); } return FileVisitResult.CONTINUE; } }); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } 

Para usar esto, solo llame

 ZipCompress.compress("target/directoryToCompress"); 

y obtendrá un archivo zip directoryToCompress.zip

 public static void main(String args[]) { omtZip("res/", "omt.zip"); } public static void omtZip(String path,String outputFile) { final int BUFFER = 2048; boolean isEntry = false; ArrayList directoryList = new ArrayList(); File f = new File(path); if(f.exists()) { try { FileOutputStream fos = new FileOutputStream(outputFile); ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos)); byte data[] = new byte[BUFFER]; if(f.isDirectory()) { //This is Directory do{ String directoryName = ""; if(directoryList.size() > 0) { directoryName = directoryList.get(0); System.out.println("Directory Name At 0 :"+directoryName); } String fullPath = path+directoryName; File fileList = null; if(directoryList.size() == 0) { //Main path (Root Directory) fileList = f; }else { //Child Directory fileList = new File(fullPath); } String[] filesName = fileList.list(); int totalFiles = filesName.length; for(int i = 0 ; i < totalFiles ; i++) { String name = filesName[i]; File filesOrDir = new File(fullPath+name); if(filesOrDir.isDirectory()) { System.out.println("New Directory Entry :"+directoryName+name+"/"); ZipEntry entry = new ZipEntry(directoryName+name+"/"); zos.putNextEntry(entry); isEntry = true; directoryList.add(directoryName+name+"/"); }else { System.out.println("New File Entry :"+directoryName+name); ZipEntry entry = new ZipEntry(directoryName+name); zos.putNextEntry(entry); isEntry = true; FileInputStream fileInputStream = new FileInputStream(filesOrDir); BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, BUFFER); int size = -1; while( (size = bufferedInputStream.read(data, 0, BUFFER)) != -1 ) { zos.write(data, 0, size); } bufferedInputStream.close(); } } if(directoryList.size() > 0 && directoryName.trim().length() > 0) { System.out.println("Directory removed :"+directoryName); directoryList.remove(0); } }while(directoryList.size() > 0); }else { //This is File //Zip this file System.out.println("Zip this file :"+f.getPath()); FileInputStream fis = new FileInputStream(f); BufferedInputStream bis = new BufferedInputStream(fis,BUFFER); ZipEntry entry = new ZipEntry(f.getName()); zos.putNextEntry(entry); isEntry = true; int size = -1 ; while(( size = bis.read(data,0,BUFFER)) != -1) { zos.write(data, 0, size); } } //CHECK IS THERE ANY ENTRY IN ZIP ? ----START if(isEntry) { zos.close(); }else { zos = null; System.out.println("No Entry Found in Zip"); } //CHECK IS THERE ANY ENTRY IN ZIP ? ----START }catch(Exception e) { e.printStackTrace(); } }else { System.out.println("File or Directory not found"); } } } 

Zip4j usa código completamente Java sin ningún soporte de código nativo, y eso es lo que lo hace más adecuado para mí. Zip4j ofrece las siguientes características:

  • Crear, Agregar, Extraer, Actualizar, Eliminar archivos de un archivo Zip
  • Leer / Escribir archivos Zip protegidos con contraseña
  • Admite el cifrado AES 128/256
  • Admite cifrado Zip estándar
  • Admite formato Zip64
  • Compatible con Store (sin compresión) y desinflar el método de compresión
  • Crear o extraer archivos de archivos Zip divididos (por ejemplo: z01, z02, … zip)
  • Admite nombres de archivos Unicode
  • Monitor de progreso

CreatePasswordProtectedZipExample.java

 import java.io.File; import java.util.ArrayList; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; public class CreatePasswordProtectedZipExample { public static void main(String[] args) { try { //This is name and path of zip file to be created ZipFile zipFile = new ZipFile("C:/temp/test.zip"); //Add files to be archived into zip file ArrayList filesToAdd = new ArrayList(); filesToAdd.add(new File("C:/temp/test1.txt")); filesToAdd.add(new File("C:/temp/test2.txt")); //Initiate Zip Parameters which define various properties ZipParameters parameters = new ZipParameters(); parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set compression method to deflate compression //DEFLATE_LEVEL_FASTEST - Lowest compression level but higher speed of compression //DEFLATE_LEVEL_FAST - Low compression level but higher speed of compression //DEFLATE_LEVEL_NORMAL - Optimal balance between compression level/speed //DEFLATE_LEVEL_MAXIMUM - High compression level with a compromise of speed //DEFLATE_LEVEL_ULTRA - Highest compression level but low speed parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); //Set the encryption flag to true parameters.setEncryptFiles(true); //Set the encryption method to AES Zip Encryption parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES); //AES_STRENGTH_128 - For both encryption and decryption //AES_STRENGTH_192 - For decryption only //AES_STRENGTH_256 - For both encryption and decryption //Key strength 192 cannot be used for encryption. But if a zip file already has a //file encrypted with key strength of 192, then Zip4j can decrypt this file parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256); //Set password parameters.setPassword("howtodoinjava"); //Now add files to the zip file zipFile.addFiles(filesToAdd, parameters); } catch (ZipException e) { e.printStackTrace(); } } } 

Controlador de inicio de spring, comprima los archivos en un directorio y puede descargarse.

 @RequestMapping(value = "/files.zip") @ResponseBody byte[] filesZip() throws IOException { File dir = new File("./"); File[] filesArray = dir.listFiles(); if (filesArray == null || filesArray.length == 0) System.out.println(dir.getAbsolutePath() + " have no file!"); ByteArrayOutputStream bo = new ByteArrayOutputStream(); ZipOutputStream zipOut= new ZipOutputStream(bo); for(File xlsFile:filesArray){ if(!xlsFile.isFile())continue; ZipEntry zipEntry = new ZipEntry(xlsFile.getName()); zipOut.putNextEntry(zipEntry); zipOut.write(IOUtils.toByteArray(new FileInputStream(xlsFile))); zipOut.closeEntry(); } zipOut.close(); return bo.toByteArray(); } 

Si desea descomprimir sin software, mejor use este código. Otro código con archivos pdf envía error en la descompresión manual

 byte[] buffer = new byte[1024]; try { FileOutputStream fos = new FileOutputStream("123.zip"); ZipOutputStream zos = new ZipOutputStream(fos); ZipEntry ze= new ZipEntry("file.pdf"); zos.putNextEntry(ze); FileInputStream in = new FileInputStream("file.pdf"); int len; while ((len = in.read(buffer)) > 0) { zos.write(buffer, 0, len); } in.close(); zos.closeEntry(); zos.close(); } catch(IOException ex) { ex.printStackTrace(); } 

Como me tomó un tiempo darme cuenta, pensé que sería útil publicar mi solución usando Java 7+ ZipFileSystem

  openZip(runFile); addToZip(filepath); //loop construct; zipfs.close(); private void openZip(File runFile) throws IOException { Map env = new HashMap<>(); env.put("create", "true"); env.put("encoding", "UTF-8"); Files.deleteIfExists(runFile.toPath()); zipfs = FileSystems.newFileSystem(URI.create("jar:" + runFile.toURI().toString()), env); } private void addToZip(String filename) throws IOException { Path externalTxtFile = Paths.get(filename).toAbsolutePath(); Path pathInZipfile = zipfs.getPath(filename.substring(filename.lastIndexOf("results"))); //all files to be stored have a common base folder, results/ in my case if (Files.isDirectory(externalTxtFile)) { Files.createDirectories(pathInZipfile); try (DirectoryStream ds = Files.newDirectoryStream(externalTxtFile)) { for (Path child : ds) { addToZip(child.normalize().toString()); //recursive call } } } else { // copy file to zip file Files.copy(externalTxtFile, pathInZipfile, StandardCopyOption.REPLACE_EXISTING); } } 

El siguiente enlace podría ayudar:

Función para crear archivos ZIP en Java