The Java implementation compresses files or folders into zip

Recently, I came across a need to download the zip package, so I found the zip tool class written by others on the Internet. But I found many blogs and always found bug s. So I wrote a tool class myself.
The functions of this tool class are:
(1) You can compress files or folders
(2) At the same time, it supports compression of multi-level folders, and recursive processing is done inside the tool
(3) Empty folders can also be compressed
(4) You can choose whether to keep the original directory structure. If not, all files will go to the root directory of the compressed package, and the empty folder will be discarded directly. Note: if the original directory structure of the file is not retained, the compression will fail when a file with the same file name is encountered.
(5) The code provides two methods to compress files. One is the folder path and the other is the file list. You can select the method according to the actual needs.

package com.tax.core.util; 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * ZipUtils
 * @author 	ZENG.XIAO.YAN
 * @date 	2017 November 19, 2007 7:16:08 PM
 * @version v1.0
 */
public class ZipUtils {
	
	private static final int  BUFFER_SIZE = 2 * 1024;
	
	/**
	 * Compress to ZIP method 1
	 * @param srcDir Compressed folder path 
	 * @param out    Compressed file output stream
	 * @param KeepDirStructure  Whether to keep the original directory structure. true: keep the directory structure; 
	 * 							false:All files run to the root directory of the compressed package (Note: if the directory structure is not reserved, files with the same name may appear, and the compression will fail)
	 * @throws RuntimeException Compression failure throws a runtime exception
	 */
	public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
			throws RuntimeException{
		
		long start = System.currentTimeMillis();
		ZipOutputStream zos = null ;
		try {
			zos = new ZipOutputStream(out);
			File sourceFile = new File(srcDir);
			compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
			long end = System.currentTimeMillis();
			System.out.println("Compression completed, time consuming:" + (end - start) +" ms");
		} catch (Exception e) {
			throw new RuntimeException("zip error from ZipUtils",e);
		}finally{
			if(zos != null){
				try {
					zos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
	/**
	 * Compress to ZIP method 2
	 * @param srcFiles List of files to be compressed
	 * @param out 	        Compressed file output stream
	 * @throws RuntimeException Compression failure throws a runtime exception
	 */
	public static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException {
		long start = System.currentTimeMillis();
		ZipOutputStream zos = null ;
		try {
			zos = new ZipOutputStream(out);
			for (File srcFile : srcFiles) {
				byte[] buf = new byte[BUFFER_SIZE];
				zos.putNextEntry(new ZipEntry(srcFile.getName()));
				int len;
				FileInputStream in = new FileInputStream(srcFile);
				while ((len = in.read(buf)) != -1){
					zos.write(buf, 0, len);
				}
				zos.closeEntry();
				in.close();
			}
			long end = System.currentTimeMillis();
			System.out.println("Compression completed, time consuming:" + (end - start) +" ms");
		} catch (Exception e) {
			throw new RuntimeException("zip error from ZipUtils",e);
		}finally{
			if(zos != null){
				try {
					zos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	
	/**
	 * Recursive compression method
	 * @param sourceFile source file
	 * @param zos		 zip Output stream
	 * @param name		 Compressed name
	 * @param KeepDirStructure  Whether to keep the original directory structure. true: keep the directory structure; 
	 * 							false:All files run to the root directory of the compressed package (Note: if the directory structure is not reserved, files with the same name may appear, and the compression will fail)
	 * @throws Exception
	 */
	private static void compress(File sourceFile, ZipOutputStream zos, String name,
			boolean KeepDirStructure) throws Exception{
		byte[] buf = new byte[BUFFER_SIZE];
		if(sourceFile.isFile()){
			// Add a zip entity to the zip output stream, and the name of the file named zip entity in the constructor
			zos.putNextEntry(new ZipEntry(name));
			// copy file to zip output stream
			int len;
			FileInputStream in = new FileInputStream(sourceFile);
			while ((len = in.read(buf)) != -1){
				zos.write(buf, 0, len);
			}
			// Complete the entry
			zos.closeEntry();
			in.close();
		} else {
			File[] listFiles = sourceFile.listFiles();
			if(listFiles == null || listFiles.length == 0){
				// When the original file structure needs to be retained, empty folders need to be processed
				if(KeepDirStructure){
					// Processing of empty folders
					zos.putNextEntry(new ZipEntry(name + "/"));
					// There is no file, and the copy of the file is not required
					zos.closeEntry();
				}
				
			}else {
				for (File file : listFiles) {
					// Determine whether the original file structure needs to be retained
					if (KeepDirStructure) {
						// Note: file Getname() needs to be preceded by the name of the parent folder plus a slash,
						// Otherwise, the original file structure cannot be retained in the final compressed package, that is, all files go to the root directory of the compressed package
						compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
					} else {
						compress(file, zos, file.getName(),KeepDirStructure);
					}
					
				}
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		/** Test compression method 1  */
		FileOutputStream fos1 = new FileOutputStream(new File("c:/mytest01.zip"));
		ZipUtils.toZip("D:/log", fos1,true);
		
		/** Test compression method 2  */
		List<File> fileList = new ArrayList<>();
		fileList.add(new File("D:/Java/jdk1.7.0_45_64bit/bin/jar.exe"));
		fileList.add(new File("D:/Java/jdk1.7.0_45_64bit/bin/java.exe"));
		FileOutputStream fos2 = new FileOutputStream(new File("c:/mytest02.zip"));
		ZipUtils.toZip(fileList, fos2);
	}
}

2, Precautions
When writing this tool class, some precautions are as follows:
(1) You can select whether to keep the original file directory structure. If not, the empty folder will not be processed directly.
(1) When encountering an empty folder, if you need to preserve the directory structure, you can directly add a ZipEntry, but the name of the entry needs to be followed by a slash (/) to indicate that it is a directory.
(2) During recursion, you do not need to close the zip output stream. The zip output stream should be closed after calling the recursive method
(3) During recursion, if it is a folder and the directory structure needs to be preserved, when calling the method to compress its sub file, you need to add a slash to the name of the folder before the name of the sub file, so that there will be multi-level directories after compression.

3, How to use this tool class in Java Web projects
The usage scenario of this tool class in web projects is multi file download. Let me simply say a case of downloading multiple excel tables.
The steps in the code are:
(1) Create a temporary folder
(2) Generate the files to be downloaded into the temporary folder
(3) After all files are generated, get the HttpServletResponse and set the downloaded header
(4) Call the method of the tool class to pass in the temporary folder path generated above and the output stream obtained by response; This will download the zip package
(5) Recursively delete the temporary folders and files generated above

The following is a code fragment of the sample code, not the complete code. Take a brief look at the steps in the code

	if(userList.size() > 0){
		/** The following is the process related to downloading the zip package */
		HttpServletRequest request = ServletActionContext.getRequest();
		FileWriter writer;
		/** 1.Create temporary folder  */
		String rootPath = request.getSession().getServletContext().getRealPath("/");
		File temDir = new File(rootPath + "/" + UUID.randomUUID().toString().replaceAll("-", ""));
		if(!temDir.exists()){
			temDir.mkdirs();
		}
		
		/** 2.Generate the files to be downloaded and store them in the temporary folder */
		// Here, let's take 10 files with the same content as an example, but the 10 file names can't be the same
		for (int i = 0; i < 10; i++) {
			dataMap.put("userList", userList);
			Map<String, String> endMap = new HashMap<>();
			endMap.put("user", "Lao Wang");
			endMap.put("time", "2017-10-10 10:50:55");
			dataMap.put("endMap", endMap);
			Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
			cfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(), "/ftl");
			Template template = cfg.getTemplate("exportExcel.ftl");
			writer = new FileWriter(temDir.getPath()+"/excel"+ i +".xls");
			template.process(dataMap, writer);
			writer.flush();
			writer.close();
		}
		
		/** 3.Set the header of the response */
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setContentType("application/zip");
		response.setHeader("Content-Disposition", "attachment; filename=excel.zip");  
		
		/** 4.Call the tool class and download the zip package */
		// We don't need to preserve the directory structure here
		ZipUtils.toZip(temDir.getPath(), response.getOutputStream(),false);
		
		/** 5.Delete temporary files and folders */
		// I didn't write recursion here, so I deleted it directly
		File[] listFiles = temDir.listFiles();
		for (int i = 0; i < listFiles.length; i++) {
			listFiles[i].delete();
		}
		temDir.delete();
	}

Put an eye in

Author: zeng1994
 source: http://www.cnblogs.com/zeng1994/
The copyright of this article belongs to the author and blog park. Welcome to reprint! However, this statement must be retained without the consent of the author, and a link to the original text must be given in an obvious position on the article page!

Keywords: Java Back-end io

Added by cornelombaard on Wed, 12 Jan 2022 11:38:46 +0200