• 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(); // 输入流关闭 
            }
        } 

    } 








  • 相关阅读:
    763. 划分字母区间(贪心算法)
    1282. 用户分组(贪心算法)
    698. 划分为k个相等的子集
    560. 和为K的子数组
    面试题 16.10. 生存人数
    Python:对列表进行排序并相应地更改另一个列表?
    数据竞赛总结
    面试提问之请你介绍一下xxx方法
    常用数学符号读法
    round() 函数
  • 原文地址:https://www.cnblogs.com/itmanxgl/p/84db9a95b5d84643580678994f6488b4.html
Copyright © 2020-2023  润新知