How to create a zip file in Java

2019-01-02 17:49发布

问题:

I have a dynamic text file that picks content from a database according to the user's query. I have to write this content into a text file and zip it in a folder in a servlet. How should I do this?

回答1:

Look at this example:

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();

This will create a Zip-File located in the root of D: named 'test.zip' which will contain one single file called 'mytext.txt'. Of course you can add more zip entries and also specify a sub directory like:

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

You can find more information about compression with java here:

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



回答2:

Java 7 has ZipFileSystem built in, that can be used to create, write and read file from zip file.

Java Doc: ZipFileSystem Provider

Map<String, String> 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); 
}


回答3:

To write a ZIP file, you use a ZipOutputStream. For each entry that you want to place into the ZIP file, you create a ZipEntry object. You pass the file name to the ZipEntry constructor; it sets the other parameters such as file date and decompression method. You can override these settings if you like. Then, you call the putNextEntry method of the ZipOutputStream to begin writing a new file. Send the file data to the ZIP stream. When you are done, call closeEntry. Repeat for all the files you want to store. Here is a code skeleton:

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();


回答4:

Here is an example code to compress a Whole Directory(including sub files and sub directories), it's using the walk file tree feature of 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<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();
        }
    }
}

To use this, just call

ZipCompress.compress("target/directoryToCompress");

and you'll get a zip file directoryToCompress.zip



回答5:

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");
    }
 }    

}


回答6:

Zip4j uses completely java code without any support of native code, and that’s what makes it a better fit for me. Zip4j provides following features:

  • Create, Add, Extract, Update, Remove files from a Zip file
  • Read/Write password protected Zip files
  • Supports AES 128/256 Encryption
  • Supports Standard Zip Encryption
  • Supports Zip64 format
  • Supports Store (No Compression) and Deflate compression method
  • Create or extract files from Split Zip files (Ex: z01, z02,…zip)
  • Supports Unicode file names
  • Progress Monitor

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<File> filesToAdd = new ArrayList<File>();
            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();
        }
    }
}


回答7:

Spring boot controller, zip the files in a directory, and can be downloaded.

@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();
}


回答8:

This is how you create a zip file from a source file:

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


回答9:

If you want decompress without software better use this code. Other code with pdf files sends error on manually decompress

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


回答10:

Since it took me a while to figure it out, I thought it would be helpful to post my solution using 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);            
    }
 }


标签: