JAVA ZIP UNZIP 文件 文件夹

这是一个Java实现的文件和文件夹压缩与解压缩的工具类,包含`ZipUtils`,提供了创建ZIP文件、解压ZIP文件的方法。代码中使用了Apache Commons Compress库来处理ZIP档案,支持GBK编码,并处理了可能出现的目录和文件名冲突问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipOutputStream;

/**
 * @author leo
 * @date 2021/12/15 16:29
 */
public class ZipUtils {

    private static final Logger log = LoggerFactory.getLogger(ZipUtils.class);

    public static void main(String[] args) {
//        zipFile("D:\\tomcat8\\tomcat8084\\temp\\leo_2020-09-01_2020-09-30", "D:\\tomcat8\\tomcat8084\\temp\\leo_2020-09-01_2020-09-30.zip");
        createZip("D:\\tomcat8\\tomcat8084\\temp\\leo_2020-09-01_2020-09-30", "D:\\tomcat8\\tomcat8084\\temp\\leo_2020-09-01_2020-09-30.zip");
        unzipFile(new File("D:\\tomcat8\\tomcat8084\\temp\\leo_2020-09-01_2020-09-30.zip"), "D:\\tomcat8\\tomcat8084\\temp\\leo_2020-09-01_2020-09-30");
    }


    private static ZipArchiveInputStream getZipFile(File zipFile) throws Exception {
        // encoding 需要注意
        return new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile)), "GBK", true);
    }

    /**
     * 解压文件
     * @param zipFile 压缩包
     * @param descDir 解压出来的文件存放目录
     */
    public static void unzipFile(File zipFile, String descDir) {
        try (ZipArchiveInputStream inputStream = getZipFile(zipFile)) {
            File pathFile = new File(descDir);
            if (!pathFile.exists()) {
                pathFile.mkdirs();
            }
            ZipArchiveEntry entry;
            while ((entry = inputStream.getNextZipEntry()) != null) {
                String entryName = entry.getName();
                if (entry.isDirectory()) {
                    File directory = new File(descDir, entryName);
                    directory.mkdirs();
                } else {
                    OutputStream os = null;
                    try {
                        if(entryName.contains("/")){
                            // 带目录的,先创建目录
                            String[] split = entryName.split("/");
                            String dirs = "";
                            for (int i = 0; i < split.length - 1; i++) {
                                dirs = dirs + split[i] + File.separator;
                            }
                            File directory = new File(descDir, dirs);
                            directory.mkdirs();
                            entryName = split[split.length -1];
                            os = new BufferedOutputStream(new FileOutputStream(new File(directory.getPath(), entryName)));
                        }else{
                            os = new BufferedOutputStream(new FileOutputStream(new File(descDir, entryName)));
                        }
                        IOUtils.copy(inputStream, os);
                    } finally {
                        IOUtils.closeQuietly(os);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 创建ZIP文件
     * @param sourcePath 文件或文件夹路径
     * @param zipPath 生成的zip文件存在路径(包括文件名)
     */
    public static void createZip(String sourcePath, String zipPath) {
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            fos = new FileOutputStream(zipPath);
            zos = new ZipOutputStream(fos);
            writeZip(new File(sourcePath), "", zos, false);
        } catch (FileNotFoundException e) {
            log.error("创建ZIP文件失败",e);
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
                if(null != fos){
                    fos.close();
                }
            } catch (IOException e) {
                log.error("创建ZIP文件失败",e);
            }

        }
    }

    /**
     * 压缩文件
     * @param file 待压缩的目录或文件
     * @param parentPath 压缩文件内的目录
     * @param zos 输出流
     * @param needAppend 是否需要创建顶层目录
     */
    private static void writeZip(File file, String parentPath, ZipOutputStream zos, boolean needAppend) {
        if(file.exists()){
            if(file.isDirectory()){
                // 处理文件夹
                if(needAppend){
                    // 需要拼接目录
                    parentPath += file.getName() + File.separator;
                }
                File [] files = file.listFiles();
                if(files.length != 0){
                    for(File f : files){
                        writeZip(f, parentPath, zos, true);
                    }
                }else{
                    // 空目录则创建当前目录
                    try {
                        zos.putNextEntry(new ZipEntry(parentPath));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }else{
                FileInputStream fis = null;
                try {
                    fis = new FileInputStream(file);
                    ZipEntry ze = new ZipEntry(parentPath + file.getName());
                    zos.putNextEntry(ze);
                    byte [] content=new byte[1024];
                    int len;
                    while((len = fis.read(content)) != -1){
                        zos.write(content,0,len);
                        zos.flush();
                    }

                } catch (FileNotFoundException e) {
                    log.error("创建ZIP文件失败",e);
                } catch (IOException e) {
                    log.error("创建ZIP文件失败",e);
                }finally{
                    try {
                        if(fis != null){
                            fis.close();
                        }
                    }catch(IOException e){
                        log.error("创建ZIP文件失败",e);
                    }
                }
            }
        }
    }

    /**
     * 压缩文件
     * @param sourceFileName 等待压缩的文件或文件夹(含目录)   D:\tomcat8\tomcat8084\temp\leo_2020-09-01_2020-09-30
     * @param targetFile 生成压缩文件名(含目录)   D:\tomcat8\tomcat8084\temp\leo_2020-09-01_2020-09-30.zip
     * @throws Exception
     */
    private static void zipFile(String sourceFileName, String targetFile) {
        ZipOutputStream out = null;
        BufferedOutputStream bos = null;
        try{
            // 创建zip输出流
            out = new ZipOutputStream( new FileOutputStream(targetFile));
            // 创建缓冲输出流
            bos = new BufferedOutputStream(out);
            File sourceFile = new File(sourceFileName);
            // 调用函数
            compress(out,bos,sourceFile,sourceFile.getName());
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                if(null != bos){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(null != out){
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 压缩文件或目录
     * @param out
     * @param bos
     * @param sourceFile
     * @param base
     * @throws Exception
     */
    private static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) throws Exception{
        // 如果路径为目录(文件夹)
        if(sourceFile.isDirectory()){
            // 取出文件夹中的文件(或子文件夹)
            File[] flist = sourceFile.listFiles();
            if(flist.length==0){
                // 如果文件夹为空,则只需在目的地zip文件中写入一个目录进入点
                try{
                    out.putNextEntry( new ZipEntry(base + "/"));
                }catch (ZipException e){
                    if(e.getMessage().contains("duplicate entry")){
                        // 重复文件名,把文件名加后缀
                        String newBase = base + "_2";
                        out.putNextEntry(new ZipEntry(newBase + "/"));
                    }else {
                        e.printStackTrace();
                    }
                }
            } else {
                // 如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
                for(int i=0;i<flist.length;i++){
                    compress(out, bos, flist[i], flist[i].getName());
                }
            }
        }else {
            // 如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中
            try{
                out.putNextEntry( new ZipEntry(base));
            }catch (ZipException e){
                if(e.getMessage().contains("duplicate entry")){
                    // 重复文件名,把文件名加后缀
                    String[] split = base.split("\\.");
                    String newBase = split[0] + "_2." + split[1];
                    out.putNextEntry( new ZipEntry(newBase));
                }else {
                    e.printStackTrace();
                }
            }
            FileInputStream fos = new FileInputStream(sourceFile);
            BufferedInputStream bis = new BufferedInputStream(fos);
            int tag;
            // 将源文件写入到zip文件中
            while((tag = bis.read()) != -1) {
                bos.write(tag);
            }
            bos.flush();
            bis.close();
            fos.close();
        }
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值