Cómo crear un archivo zip en Java

149

Tengo un archivo de texto dinámico que recoge 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?

Ashish Agarwal
fuente

Respuestas:

231

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 archivo zip en la raíz de D:named test.zipque contendrá un solo archivo llamado mytext.txt. Por supuesto, puede agregar más entradas zip y también especificar un subdirectorio como este:

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

Puede encontrar más información sobre la compresión con Java aquí .

Chris
fuente
1
¿Por qué se incluyen las dos líneas byte[] data = sb.toString().getBytes(); out.write(data, 0, data.length);en este ejemplo de código? ¿Cuál es su propósito?
Kaadzia
@kdzia, la primera línea convierte el valor de StringBuilder en una matriz de bytes, y la segunda línea toma esa matriz de bytes y la escribe en ZipEntry dentro del archivo "test.zip". Estas líneas son necesarias porque los archivos Zip funcionan con conjuntos de bytes, no con cadenas.
OrangeWombat
3
Pero ... en el ejemplo anterior, ¿cómo tiene el StringBuilder algo más que "Test String"? Estoy un poco confundido por esto también. Si está escribiendo el sb.toString().getBytes()archivo ZIP, ¿espero que desee que contenga los bytes del archivo que está comprimiendo? ¿O me estoy perdiendo algo?
RobA
3
@RobA no te estás perdiendo nada. El StringBuilder está destinado a contener el texto que el OP obtuvo de su base de datos. OP simplemente tendría que reemplazar "prueba de la cuerda" (incluyendo las comillas) para algo así como getTextFromDatabase ()
Blueriver
Gracias, @Blueriver
RobA
143

Java 7 tiene ZipFileSystem integrado, que puede usarse para crear, escribir y leer archivos desde archivos zip.

Java Doc: proveedor de ZipFileSystem

Map<String, String> env = new HashMap<>();
// Create the zip file if it doesn't exist
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); 
}
Sivabalan
fuente
1
¿Hay alguna manera de hacer que esto funcione si la extensión no lo es .zip? Necesito escribir un .fooarchivo, que está formateado exactamente como un archivo zip, pero con una extensión diferente. Sé que podría hacer un .ziparchivo y renombrarlo, pero crearlo con el nombre correcto sería más simple.
Troy Daniels
2
@TroyDaniels, el ejemplo anterior también funciona con una extensión diferente, ya que utiliza el jar:file:prefijo para crear URI.
Sivabalan
10
El único problema que puede aparecer aquí es que no funcionará en caso de que tenga directorios. Entonces, por ejemplo, si tiene "/dir/SomeTextFile.txt" en la pathInZipfilevariable, debe crear el 'dir' dentro del archivo .zip. Para esto, solo agregue la siguiente línea: Files.createDirectories(pathInZipfile.getParent())antes de invocar el Files.copymétodo.
D. Naumovich
¿Cómo establecer el nivel de compresión?
cdalxndr
34

Para escribir un archivo ZIP, utiliza un ZipOutputStream. Para cada entrada que desee colocar en el archivo ZIP, cree un objeto ZipEntry. 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 haya terminado, 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();
WiseGeek
fuente
22

Aquí hay un código de ejemplo para comprimir un directorio completo (incluidos los subarchivos y subdirectorios), está utilizando la función de árbol de archivos de caminata 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) {
        final Path sourceDir = Paths.get(dirPath);
        String zipFileName = dirPath.concat(".zip");
        try {
            final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFileName));
            Files.walkFileTree(sourceDir, new SimpleFileVisitor<Path>() {
                @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 directorio de archivo zip ToCompress.zip

Owen Cao
fuente
4

Controlador de arranque de Spring, comprime los archivos en un directorio y se puede descargar.

@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();
}
Yuiffy
fuente
2
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<String> directoryList = new ArrayList<String>();
    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");
    }
 }    

}
Dhiral Pandya
fuente
2

Así es como se crea un archivo zip desde un archivo fuente:

String srcFilename = "C:/myfile.txt";
String zipFile = "C:/myfile.zip";

try {
    byte[] buffer = new byte[1024];
    FileOutputStream fos = new FileOutputStream(zipFile);
    ZipOutputStream zos = new ZipOutputStream(fos);         
    File srcFile = new File(srcFilename);
    FileInputStream fis = new FileInputStream(srcFile);
    zos.putNextEntry(new ZipEntry(srcFile.getName()));          
    int length;
    while ((length = fis.read(buffer)) > 0) {
        zos.write(buffer, 0, length);
    }
    zos.closeEntry();
    fis.close();
    zos.close();            
}
catch (IOException ioe) {
    System.out.println("Error creating zip file" + ioe);
}
vive el amor
fuente
1

Fila india:

String filePath = "/absolute/path/file1.txt";
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    File fileToZip = new File(filePath);
    zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
    Files.copy(fileToZip.toPath(), zipOut);
}

Archivos múltiples:

List<String> filePaths = Arrays.asList("/absolute/path/file1.txt", "/absolute/path/file2.txt");
String zipPath = "/absolute/path/output.zip";

try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))) {
    for (String filePath : filePaths) {
        File fileToZip = new File(filePath);
        zipOut.putNextEntry(new ZipEntry(fileToZip.getName()));
        Files.copy(fileToZip.toPath(), zipOut);
    }
}
Pavel
fuente
1

Tiene que crear principalmente dos funciones. Primero es writeToZipFile () y segundo es createZipfileForOutPut .... y luego llama a createZipfileForOutPut ('nombre de archivo de .zip') `...

 public static void writeToZipFile(String path, ZipOutputStream zipStream)
        throws FileNotFoundException, IOException {

    System.out.println("Writing file : '" + path + "' to zip file");

    File aFile = new File(path);
    FileInputStream fis = new FileInputStream(aFile);
    ZipEntry zipEntry = new ZipEntry(path);
    zipStream.putNextEntry(zipEntry);

    byte[] bytes = new byte[1024];
    int length;
    while ((length = fis.read(bytes)) >= 0) {
        zipStream.write(bytes, 0, length);
    }

    zipStream.closeEntry();
    fis.close();
}

public static void createZipfileForOutPut(String filename) {
    String home = System.getProperty("user.home");
   // File directory = new File(home + "/Documents/" + "AutomationReport");
    File directory = new File("AutomationReport");
    if (!directory.exists()) {
        directory.mkdir();
    }
    try {
        FileOutputStream fos = new FileOutputStream("Path to your destination" + filename + ".zip");
        ZipOutputStream zos = new ZipOutputStream(fos);

        writeToZipFile("Path to file which you want to compress / zip", zos);


        zos.close();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Tarpan Patel
fuente
0

Si quieres descomprimir sin software mejor usa este código. Otro código con archivos pdf envía un error al descomprimir manualmente

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();
    }
cmujica
fuente
0

Como me tomó un tiempo resolverlo, 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<String, String> 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<Path> 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);            
    }
 }
Siraj K
fuente
0
public static void zipFromTxt(String zipFilePath, String txtFilePath) {
    Assert.notNull(zipFilePath, "Zip file path is required");
    Assert.notNull(txtFilePath, "Txt file path is required");
    zipFromTxt(new File(zipFilePath), new File(txtFilePath));
}

public static void zipFromTxt(File zipFile, File txtFile) {
    ZipOutputStream out = null;
    FileInputStream in = null;
    try {
        Assert.notNull(zipFile, "Zip file is required");
        Assert.notNull(txtFile, "Txt file is required");
        out = new ZipOutputStream(new FileOutputStream(zipFile));
        in = new FileInputStream(txtFile);
        out.putNextEntry(new ZipEntry(txtFile.getName()));
        int len;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
            out.flush();
        }
    } catch (Exception e) {
        log.info("Zip from txt occur error,Detail message:{}", e.toString());
    } finally {
        try {
            if (in != null) in.close();
            if (out != null) {
                out.closeEntry();
                out.close();
            }
        } catch (Exception e) {
            log.info("Zip from txt close error,Detail message:{}", e.toString());
        }
    }
}
鄒成立
fuente
0

Dado exportPathy queryResultscomo variables de cadena, el siguiente bloque crea un results.ziparchivo debajo exportPathy escribe el contenido queryResultsen un results.txtarchivo dentro del zip.

URI uri = URI.create("jar:file:" + exportPath + "/results.zip");
Map<String, String> env = Collections.singletonMap("create", "true");

try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
  Path filePath = zipfs.getPath("/results.txt");
  byte[] fileContent = queryResults.getBytes();

  Files.write(filePath, fileContent, StandardOpenOption.CREATE);
}
Camilo Silva
fuente
0

Usando Jeka https://jeka.dev JkPathTree, es bastante sencillo.

Path wholeDirToZip = Paths.get("dir/to/zip");
Path zipFile = Paths.get("file.zip");
JkPathTree.of(wholeDirToZip).zipTo(zipFile);
Jerome Angibaud
fuente
0

Hay otra opción al usar zip4jen https://github.com/srikanth-lingala/zip4j

Crear un archivo zip con un solo archivo / Agregar un solo archivo a un zip existente

new ZipFile("filename.zip").addFile("filename.ext"); O

new ZipFile("filename.zip").addFile(new File("filename.ext"));

Crear un archivo zip con múltiples archivos / Agregar múltiples archivos a un zip existente

new ZipFile("filename.zip").addFiles(Arrays.asList(new File("first_file"), new File("second_file")));

Crear un archivo zip al agregarle una carpeta / Agregar una carpeta a un zip existente

new ZipFile("filename.zip").addFolder(new File("/user/myuser/folder_to_add"));

Crear un archivo zip desde una secuencia / Agregar una secuencia a un zip existente new ZipFile("filename.zip").addStream(inputStream, new ZipParameters());

sendon1982
fuente