java压缩与解压缩

主要用到apache的ant.jar,也可用jdk的相关类,但会有中文乱码问题。最重要的俩类是ZipFile和ZipEntry,前者将zip文件转为java对象,后者将zip文件中的条目文件转为java对象。
核心代码如下:

压缩代码:

ZipOutputStream zipOs = new ZipOutputStream(fos);
ZipEntry zipEntry = new ZipEntry("entryName");
zipOs.putNextEntry(zipEntry);

解压缩代码:

Enumeration<ZipEntry> entries = zipFile.getEntries();
ZipEntry zipEntry = entries.nextElement();
InputStream ins = zipFile.getInputStream(zipEntry);

需要注意的地方:

针对空文件夹需要特殊处理,需要往Entry中放入”/“+文件夹名+“/“项

zipOs.putNextEntry("/");

详细点的练习:

/**
 * 测试文件压缩与解压缩
 *
 */
public class TestZip {

    public static void main(String[] args) {
        //-->压缩单个文件
        zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst\\新建文本文档.zip", "D:\\BIZFLOW\\src\\tst\\新建文本文档.txt");
        //-->压缩文件夹
        //zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst.zip", "D:\\BIZFLOW\\src\\tst");
        //-->压缩多个文件(不指定压缩文件保存路径)
        //zipMultiFiles("","D:\\BIZFLOW\\src\\tst\\新建文本文档.txt","D:\\BIZFLOW\\src\\tst\\新建文本文档 - 副本.txt");
        //-->压缩多个文件(指定压缩文件保存路径)
        //zipMultiFiles("D:\\BIZFLOW\\src\\tst\\新建.zip","D:\\BIZFLOW\\src\\tst\\新建文本文档.txt","D:\\BIZFLOW\\src\\tst\\新建文本文档 - 副本.txt");
        //-->解压缩文件
        //unzipFile("D:\\BIZFLOW\\src\\tst\\新建", "D:\\BIZFLOW\\src\\tst\\新建文本文档.txt等.zip");
    }

    /**
     * 压缩单个文件/文件夹
     * @param destPath 压缩文件保存路径(为空串/null时默认压缩路径:待压缩文件所在目录,压缩文件名为待压缩文件/文件夹名+“等.zip”)
     * @param srcPath 待压缩的文件路径
     */
    public static void zipSingleFileOrFolder(String destPath, String srcPath) {
        if(StringUtils.isBlank(srcPath)) {
            throw new RuntimeException("待压缩文件夹不可为空!");
        }
        if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {
            throw new RuntimeException("保存文件名应以.zip结尾!");
        }
        File file = new File(srcPath);
        if(!file.exists()) {
            throw new RuntimeException("路径'"+srcPath+"'下未找到文件");
        }
        if(file.isDirectory()) {
            //压缩文件夹
            zipFolder(destPath, srcPath);
        } else {
            //压缩单个文件
            zipFile(destPath, srcPath); 
        }
    }

    /**
     * 压缩多个文件
     * @param destPath 压缩文件保存路径(为空串/null时默认压缩路径:待压缩文件所在目录,压缩文件名为第一个待压缩文件名+“等.zip”)
     * @param srcPaths 待压缩文件路径集合
     */
    public static void zipMultiFiles(String destPath, String...srcPaths) {
        if(srcPaths==null || srcPaths.length==0) {
            throw new RuntimeException("待压缩文件夹不可为空!");
        }
        if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {
            throw new RuntimeException("保存文件名应以.zip结尾!");
        }
        zipFiles(destPath, srcPaths);
    }

    /**
     * 解压缩文件
     * @param destPath 解压缩路径(为空串/null时默认解压缩路径:压缩文件所在目录)
     * @param zipPath 压缩文件路径
     */
    public static void unzipFile(String destPath, String zipPath) {
        if(StringUtils.isBlank(zipPath)) {
            throw new RuntimeException("压缩文件路径不可为空!");
        }
        if(!zipPath.endsWith(".zip")) {
            throw new RuntimeException("保存文件名应以.zip结尾!");
        }
        File file = new File(zipPath);
        if(StringUtils.isBlank(destPath)) {
            destPath = getUnzipBasePath(file);
        }
        if(!file.exists()) {
            throw new RuntimeException("路径'"+zipPath+"'下未找到文件");
        }
        ZipFile zipFile;
        int len;
        byte[] buff = new byte[1024];
        try {
            zipFile = new ZipFile(zipPath);
            //获取压缩文件中所有条目
            Enumeration<ZipEntry> entries = zipFile.getEntries();
            if(entries!=null) {
                while(entries.hasMoreElements()) {
                    //压缩文件条目转为文件或文件夹
                    ZipEntry zipEntry = entries.nextElement();
                    //获取输入流
                    InputStream ins = zipFile.getInputStream(zipEntry);
                    BufferedInputStream bis = new BufferedInputStream(ins);
                    File unzipFile = new File(destPath+File.separator+zipEntry.getName());
                    if(zipEntry.isDirectory()) {
                        unzipFile.mkdirs();
                        continue;
                    } 

                    File pf = unzipFile.getParentFile();
                    if(pf!=null && !pf.exists()) {
                        pf.mkdirs();
                    }
                    unzipFile.createNewFile();
                    FileOutputStream fos = new FileOutputStream(unzipFile);
                    BufferedOutputStream bos = new BufferedOutputStream(fos);
                    //输出流写文件
                    while((len=bis.read(buff, 0, 1024))!=-1) {
                        bos.write(buff, 0, len);
                    }
                    bos.flush();
                    fos.close();
                    bos.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }

    }

    /**
     * 获取解压缩文件基路径
     * @param zipPath
     * @return 
     */
    private static String getUnzipBasePath(File zipPath) {
        return zipPath.getParentFile().getAbsolutePath();
    }

    /**
     * 压缩单个文件
     * @param destPath 压缩文件保存路径
     * @param srcPath 待压缩文件路径
     */
    private static void zipFile(String destPath, String srcPath) {
        zipFiles(destPath, srcPath);
    }
    /**
     * 压缩多个文件
     * @param srcPath
     * @param zipPath
     */
    private static void zipFiles(String destPath, String...srcPaths) {
        if(StringUtils.isBlank(destPath)) {
            File srcFile0 = new File(srcPaths[0]);
            destPath = srcFile0.getParentFile().getAbsolutePath()+File.separator+srcFile0.getName()+"等.zip";
        }
        File zipFile = new File(destPath);
        FileOutputStream fos = null;
        try {
            zipFile.createNewFile();
            zipFile.mkdirs();
            fos = new FileOutputStream(zipFile);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
        //获取输出流
        ZipOutputStream zipOs = new ZipOutputStream(fos);
        //循环将多个文件转为压缩文件条目
        for(String srcPath : srcPaths) {
            if(StringUtils.isBlank(srcPath)) {
                throw new RuntimeException("待压缩文件路径不可为空!");
            }
            File srcFile = new File(srcPath);
            try {
                ZipEntry zipEntry = new ZipEntry(srcFile.getName());
                zipOs.putNextEntry(zipEntry);
                //获取输入流
                FileInputStream fis = new FileInputStream(srcFile);
                int len;
                byte[] buff = new byte[1024];
                //输入/输出流对拷
                while((len=fis.read(buff))!=-1) {
                    zipOs.write(buff, 0, len);
                }
                fis.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                throw new RuntimeException();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException();
            }
        }
        try {
            zipOs.flush();
            zipOs.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    /**
     * 压缩文件夹
     * @param destPath 压缩文件保存路径
     * @param srcPath 待压缩文件夹路径
     */
    private static void zipFolder(String destPath, String srcPath) {
        File srcFile = new File(srcPath);
        //如压缩文件保存路径为空,则默认保存路径
        if(StringUtils.isBlank(destPath)) {
            destPath = srcFile.getParent()+File.separator+srcFile.getName()+".zip";
        }
        FileOutputStream fos = null;
        ZipOutputStream zipOs = null;
        try {
            fos = new FileOutputStream(destPath);
            zipOs = new ZipOutputStream(fos);
            //递归往压缩文件中添加文件夹条目
            zipFolder(srcFile, srcFile, zipOs);
            zipOs.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    /**
     * 递归往压缩文件中添加文件夹条目
     * @param srcFile 待压缩文件夹路径
     * @param baseFile 
     * @param zipOs
     */
    private static void zipFolder(File srcFile, File baseFile, ZipOutputStream zipOs) {
        int len;
        byte[] buff = new byte[1024];
        if(srcFile.isDirectory()) {
            //针对空文件夹需要特殊处理,需要往Entry中放入"/"+文件夹名+"/"项
            try {
                zipOs.putNextEntry(new ZipEntry(srcFile.getAbsolutePath().replaceFirst(baseFile.getParentFile().getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"), "")+"/"));
                zipOs.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException();
            }
            //获取当前文件夹下文件列表
            File[] fileLists = srcFile.listFiles();
            if(fileLists!=null && fileLists.length>0) {
                for (int i = 0; i < fileLists.length; i++) {
                    //递归往压缩文件中添加文件夹条目
                    zipFolder(fileLists[i], baseFile, zipOs);
                }
            }
        } else {
            //文件处理比较简单,直接放入Entry
            try {
                FileInputStream fis = new FileInputStream(srcFile);
                zipOs.putNextEntry(new ZipEntry(getRelativePath(baseFile.getAbsolutePath(), srcFile)));
                while((len=fis.read(buff))!=-1) {
                    zipOs.write(buff, 0, len);
                }
                zipOs.closeEntry();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException();
            }
        }
    }

    /**
     * 获取相对基路径的相对路径
     * @param basePath
     * @param file
     * @return
     */
    private static String getRelativePath(String basePath, File file) {
        if(!basePath.equalsIgnoreCase(file.getAbsolutePath())) {
            return getRelativePath(basePath, file.getParentFile())+File.separator+file.getName();
        } else {
            return file.getName();
        }
    }

}

你可能感兴趣的:(java,压缩,解压缩)