java zip

使用 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)