java zip

作者: 蕪園樓主香獨秀 | 来源:发表于2016-11-06 21:32 被阅读206次

    使用 java 原生 api 实现简单压缩
    关键类:ZipOutputStream,ZipEntry

    • ZipOutputStream 压缩流,用与将数据写入 zip 中
    • ZipEntry 描述了 zip 文件的内部结构,ZipEntry 中存放着文件路径与文件数据的映射
      eg: /mm/hello.java --> hello.java文件 ; /mm/nn/world.js --> world.js文件
      因此在解压的时候就可以通过读取 ZipEntry 创建相对应的路径,再将文件数据写入对应路径,即可完成解压
    • zipOutputStream.putNextEntry(zipEntry) ,zipInputStream.getNextEntry()
    • java 原生 zip api 不支持中文,所以压缩中又出现中文字符的文件名时会出现乱码的情况
    • 解决方法: 下载 apache-ant-zip.jar 使用 apache提供的 ZipOutputStream , ZipEntry,zipOutputStream.setEncoding("");

    示例代码😜:

    /**
     * java zip解压缩工具
     * zip文件中可以存在空目录,可以设置是否包含顶层目录 eg: /mm: (1.txt,nn/) --> xx.zip: (1.txt,mm/) (没有顶层目录mm)
     * @Description: TODO 
     * @CreateTime: 2016年11月5日 下午5:31:41 
     * @author: 蕪園樓主  
     * @version V1.0
     */
    public final class ZipUtil {
     
        private static byte[] buffer = new byte[1024 * 10]; //压缩缓冲
     
        private ZipUtil() {
            // empty
        }
     
        /**
         * 压缩一个目录
         * @Description: TODO  
         * @CreateTime: 2016年11月5日 下午5:29:15 
         * @author: 蕪園樓主 
         * @param filePath 源文件绝对路径
         * @param zipFilePath zip文件绝对路径 (如果此处是目录名,则默认使用源文件名作为zip文件名)
         * @param keepTopDir zip文件中是否包含顶层目录
         * @return
         */
        public static File zipDir(String filePath, String zipFilePath, boolean keepTopDir) {
            File target = null;
            File source = new File(filePath);
            if(!source.exists() || !source.isDirectory()){
                return null;
            }
            
            target = new File(zipFilePath);
            
            if(target.isDirectory()){ //如果是目录,则压缩文件名为源文件名
                target = new File(target.getAbsolutePath(), source.getName().concat(".zip")); 
            }else if (target.isFile()) {
                target.delete(); // 删除旧的文件
            }else{ //不存在
                if(! target.getName().matches(".+\\..+$")){  //一个不存在的目录,以是否有扩展名为判断是否是一个目录
                    target.mkdirs();
                    target = new File(target.getAbsolutePath(), source.getName().concat(".zip")); 
                }else{ //一个不存在的文件
                    if(! target.getParentFile().exists()){
                        target.getParentFile().mkdirs();
                    }
                }
            }
            
            
            
            FileOutputStream fos = null;
            ZipOutputStream zos = null;
            try {
                fos = new FileOutputStream(target);
                zos = new ZipOutputStream(new BufferedOutputStream(fos));
             // 添加对应的文件Entry
                addEntry("", source, zos, keepTopDir);
            } catch (IOException e) {
                throw new RuntimeException(e);
            } finally {
                //关闭流
            }
            return target;
        }
        /**
         * 压缩一个文件
         * @Description: TODO  
         * @CreateTime: 2016年11月5日 下午5:27:10 
         * @author: 蕪園樓主 
         * @param filePath 源文件绝对路径
         * @param zipDir zip文件父目录
         * @param zipName zip文件名 (如果此处是目录名,则默认使用源文件名作为zip文件名)
         * @return
         */
        public static File zipFile(String filePath, String zipFilePath) throws Exception{
            
            File target = null;
            File source = new File(filePath);
            if(!source.exists() || !source.isFile()){    
                throw new Exception("压缩源目录无效");
            }
            
            target = new File(zipFilePath);
            
            if(target.isDirectory()){ //如果是目录,则压缩文件名为源文件名
                target = new File(target.getAbsolutePath(), source.getName().concat(".zip")); 
            }else if (target.isFile()) {
                target.delete(); // 删除旧的文件
            }else{ //不存在
                if(! target.getName().matches("\\..+$")){  //一个不存在的目录,以是否有扩展名为判断是否是一个目录
                    target.mkdirs();
                    target = new File(target.getAbsolutePath(), source.getName().concat(".zip")); 
                }else{
                    target.getParentFile().mkdirs();
                }
            }
            
            
            FileOutputStream fos = null;
            ZipOutputStream zos = null;
            try {
                fos = new FileOutputStream(target);
                zos = new ZipOutputStream(new BufferedOutputStream(fos));
                zos.setEncoding("utf-8"); //设置编码
             // 添加对应的文件Entry
                addEntry("", source, zos, true);
            } catch (IOException e) {
                throw new Exception("压缩文件内部结构构建失败");
            } finally {
                closeQuietly(zos, fos);
            }
            return target;
        }
     
        /**
         * 
         * @Description: 压缩文件,构建压缩内部文件结构  
         * @CreateTime: 2016年11月5日 下午5:23:48 
         * @author: 蕪園樓主 
         * @param base 
         * @param source 被压缩源文件
         * @param zos 压缩输出流
         * @param dir 压缩文件中是否包含顶层目录
         * @throws IOException
         */
        private static void addEntry(String base, File source, ZipOutputStream zos, boolean dir)
                throws IOException {
            String entry = (dir) ? (base.concat(source.getName())) : base;
            if (source.isDirectory()) {
                File[] files = source.listFiles();
                if(files == null || files.length < 1){ //空目录
                    zos.putNextEntry(new ZipEntry(entry));
                    zos.closeEntry();
                    return;
                }
                for (File file : files) {
                    // 递归列出目录下的所有文件,添加文件Entry
                    addEntry(((dir)?(entry.concat("/")):entry), file, zos, true);
                }
            } else {
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    fis = new FileInputStream(source);
                    bis = new BufferedInputStream(fis, buffer.length);
                    int read = 0;
                    zos.putNextEntry(new ZipEntry(entry));
                    while ((read = bis.read(buffer, 0, buffer.length)) != -1) {
                        zos.write(buffer, 0, read);
                    }
                    zos.closeEntry();
                } 
                finally {
                    //关闭流
                }
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:java zip

          本文链接:https://www.haomeiwen.com/subject/elhwuttx.html