zoukankan      html  css  js  c++  java
  • zip文件压缩

    zip文件结构
         
         上面中的每一行都是一个条目,zip文件就是由一个或者多个条目组成。
         条目在Java中对应ZipEntry类
         

    创建zip压缩文件
         知道了zip文件结构之后,大概就知道怎么去创建一个zip压缩文件了。
         之前,先了解下创建普通的文件都是经过以下几个步骤:
         1、创建文件输出流FileOutputStream fout = new FileOutputStream(new File("XXX"));
         2、往文件输出流中写入文件内容,fout.write(XXX);
         3、关闭输出流fout.close();
         这样,一个普通的创建就是生成了

         既然zip压缩文件也是文件,那么它的创建也基本都差不多,只是,zip文件结构跟普通文件有点差别,因为它里面是由条目(ZipEntry)组成的。
         所以创建zip压缩文件的步骤如下:
         1、创建zip压缩文件输出流
               ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File("XXX")));

         2、创建zip文件条目
               ZipEntry entry = new ZipEntry(name)
               备注:name指定条目的名称,例如上图显示的client.cer,这里name可以带路径,例如:a/b/c/test.txt,这样就是创建a/b/c这个目录。

         3、将条目添加到zip文件输出流
              zos.putNextEntry(entry);
         
         4、创建被文件的输入流,读取文件内容,并写入到zip压缩文件输出流。这个时候,写入的内容都属于当前这个条目的。
             FileInputStream in = new FileInputStream(new File("XXX"));
         byte[]buffer = new byte[1024];
         int len = 0;
         while((len = in.read(buffer))!=-1){
              zos.write(buffer ,0 ,len);
         }
         in.close();

         
         5、关闭zip文件输出流
             zos.close()


    zip乱码问题解决
           使用Apache中的org.apache.tools.zip.ZipOutputStream类来替换Java自带的ZipOutputStream类
           FileOutputStream fout = new FileOutputStream("f:\abc.zip");
        ZipOutputStream out = new ZipOutputStream(fout);
        out.setEncoding("utf-8"); //这条语句时必须的,否则,生成中文条目时,无法打开zip文件或者出现乱码
        ZipEntry entry = new ZipEntry("测试文件.txt");
        out.putNextEntry(entry);

    误解区:
        以前都是以为一个文件或者目录就对应zip文件中的一个条目,其实并非一定是这样的。解析如下:
        zip文件是以条目来组织,操作zip文件都是基于条目来进行的,因此,每次往条目新增内容时,
        得首先创建zip文件条目,并将添加到zip文件输出,之后,zip输出流,才认为之后写入到输出流中的
        内容都是属于这个条目,直到zip输出流中新增新的条目。不过一般来正常来说,都是一个文件或者目录就对应zip文件中的一个条目。
        
        正常情况下,一个文件或者目录对应一个条目,如下图:
        
           
           但是也可以将a.txt、b.txt的内容都只写入的一个条目c.txt
           

           生成的zip文件结果图:
           
           这里可以发现,只要没有重新往zip文件输出流中添加新的条目,那么,所有的内容都是写入当前条目中。


    自己封装的一个zip压缩工具类
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.ArrayList;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    public class FilleUtils {
        
        
        /**
         * zip压缩文件,默认生成的压缩文件目录与当前需要压缩的文件或者目录同级
         * @param filePath  需要压缩的文件或者目录
         * @return 返回zip压缩文件路径
         */
        public static String zip(String filePath) throws Exception{
             System.out.println("压缩中..."); 
             String zipFilePath = null;
             File srcFile = new File(filePath);
             
             //获得zip文件路径
             if(srcFile.isDirectory()){
                 zipFilePath = srcFile.getParent() + srcFile.getName() + ".zip";
             }
             else{
                 String zipFileName = "";
                 if(srcFile.getName().indexOf(".")>-1)
                     zipFileName = srcFile.getName().substring(0 ,srcFile.getName().lastIndexOf(".")) + ".zip";
                 else
                     zipFileName = srcFile.getName() + ".zip";
                 zipFilePath = srcFile.getParent() + zipFileName;
             }
             
             //开始进行压缩
             ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));   
             BufferedOutputStream bo = new BufferedOutputStream(out);  
             zip(out, srcFile, srcFile.getName(), bo);  
             bo.close();  
             out.close(); 
             System.out.println("压缩完成");  
             
             return zipFilePath;
        }
        
        
        /**
         * zip压缩文件
         * @param filePath
         * @param zipFilePath
         */
        public static void zip(String filePath ,String zipFilePath) throws Exception{
             System.out.println("压缩中..."); 
             File srcFile = new File(filePath);
             
             //检查压缩文件路径是否存在,不存在则创建
             File zipFile = new File(zipFilePath);
             if(!zipFile.exists()){
                 zipFile.getParentFile().mkdirs();
             }
             
             //开始压缩
             ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));   
             BufferedOutputStream bo = new BufferedOutputStream(out);  
             zip(out, srcFile, srcFile.getName(), bo);  
             bo.close();  
             out.close();  
             System.out.println("压缩完成");  
        }
        
        
        
        /**
         * 压缩指定的多个文件或者目录
         * @param filePathList
         * @param zipFilePath
         * @throws Exception
         */
        public static void zip(ArrayList<String> filePathList , String zipFilePath) throws Exception{
             System.out.println("压缩中...");
             //检查压缩文件路径是否存在,不存在则创建
             File zipFile = new File(zipFilePath);
             if(!zipFile.exists()){
                 zipFile.getParentFile().mkdirs();
             }
            
             //开始压缩
             ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilePath));  
             BufferedOutputStream bo = new BufferedOutputStream(out); 
             if(filePathList==null || filePathList.size()==0){
                 throw new RuntimeException("没有指定需要压缩的文件");
             }
             for(String filePath :filePathList){
                 File srcFile = new File(filePath);
                 zip(out, srcFile, srcFile.getName(), bo); 
             }
             bo.close();  
             out.close(); 
             System.out.println("压缩完成"); 
        }
        
        
        
        private static void zip(ZipOutputStream out , File srcFile ,String base ,BufferedOutputStream bo) throws Exception{
            
            //如果需要压缩的文件是目录,则进行递归压缩处理
            if(srcFile.isDirectory()){
                File[] fileList = srcFile.listFiles();  
                
                //如果是空目录,也需要将该目录压缩进去,注意,此时zipentry的name必须以“/"结束
                if (fileList.length == 0) {  
                    out.putNextEntry(new ZipEntry(base + "/")); // 创建zip压缩进入点base  
                    out.closeEntry();
                }  
                for (int i = 0; i < fileList.length; i++) {  
                    zip(out, fileList[i], base + "/" + fileList[i].getName(), bo); // 递归遍历子文件夹  
                } 
            }
            else{
                out.putNextEntry(new ZipEntry(base)); // 创建zip压缩进入点base  
                FileInputStream in = new FileInputStream(srcFile);  
                byte[]buffer = new byte[1024];
                int len = 0;
                while((len = in.read(buffer))!=-1){
                    out.write(buffer ,0 ,len);
                }  
                in.close(); // 输入流关闭 
            }
        } 

    } 








  • 相关阅读:
    POJ 3253 Fence Repair
    POJ 2431 Expedition
    NYOJ 269 VF
    NYOJ 456 邮票分你一半
    划分数问题 DP
    HDU 1253 胜利大逃亡
    NYOJ 294 Bot Trust
    NYOJ 36 最长公共子序列
    HDU 1555 How many days?
    01背包 (大数据)
  • 原文地址:https://www.cnblogs.com/itmanxgl/p/84db9a95b5d84643580678994f6488b4.html
Copyright © 2011-2022 走看看