• java 压缩与解压


    最近复习到IO,想找个案例做一做,恰好下载了许多图片压缩包,查看图片很不方便,所以打算用IO把图片都解压到同一个文件夹下。然后集中打包。

    本例使用jdk自带的ZipInputStream和ZipOutPutStream,功能有限不支持rar但是api很简单。

    import java.io.*;
    import java.util.zip.*;
    
    /**
     * Created by tm on 2017/2/18.
     * time : 17:33
     * project_name : toolSite
     * 提供zip文件和文件夹的解压和压缩功能。
     */
    public class ZipTool {
    
        /**
         * 压缩单个文件
         * 此处传参都是绝对路径。
         * @param src 源文件绝对路径名
         * @param destPath 将生成的压缩包绝对路径(路径以/结尾)
         * @param destName 将生成的压缩包文件名
         * @throws IOException
         */
        public static void compressFile(String src, String destPath,String destName) throws IOException {
            File f = new File(src);
            if (!f.exists()) {
                throw new RuntimeException("file not find ");
            }
    
            File folder = new File(destPath);
            if(!folder.exists()){
                folder.mkdir();
            }
    
            InputStream is = new FileInputStream(f);
            BufferedInputStream buffIn = new BufferedInputStream(is);
            //创建文件File,创建文件输出流,包装到Zip文件输出处理流上,最后把Zip处理流再包装到Buffer缓冲输出流中。
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(destPath+destName)));
            BufferedOutputStream buffOut = new BufferedOutputStream(zos);
            //需要将文件项put到entry中,解压文件时从此entry中获取数据。
            zos.putNextEntry(new ZipEntry(f.getName()));
    
            //b是指the next byte of data
            int b;
            while ((b = buffIn.read()) != -1) {
                buffOut.write(b);
            }
    
            buffIn.close();
            buffOut.flush();
            buffOut.close();
        }
    
        /**
         * 解压单个zip文件(上面压缩后的解压,认为不包含子文件夹)
         * @param src 源zip的绝对路径
         * @param dest 解压的目标文件夹(路径以/结尾)
         * @throws IOException
         */
        public static void unCompress(String src, String dest) throws IOException {
            File file = new File(src);
            if(!file.exists()){
                throw new RuntimeException("zip file not found");
            }
    
            File d = new File(dest);
            if(!d.exists()){
                d.mkdir();
            }
    
            InputStream is = new FileInputStream(file);
            ZipInputStream zis = new ZipInputStream(is);
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                //解压文件需要从zip中读取每一个entry,一个一个地outPut出来
                OutputStream out = new FileOutputStream(new File(dest + entry.getName()));
                BufferedOutputStream bos = new BufferedOutputStream(out);
                BufferedInputStream buffIn = new BufferedInputStream(new ZipFile(file).getInputStream(entry));
                int b;
                while ((b = buffIn.read()) != -1) {
                    bos.write(b);
                }
                bos.flush();
                buffIn.close();
                bos.close();
            }
            zis.close();
        }
    
        /**
         * 压缩指定的文件夹(代码里没有对路径做校验,读者可自行添加,参考上例)
         * @param srcFolder 源文件夹
         * @param destFileName 目标文件名
         * @throws IOException
         */
        public static void compressNestFolder(String srcFolder, String destFileName) throws IOException {
            System.out.println(">>>>>>>>>>开始压缩");
            File folder = new File(srcFolder);
            if (!folder.exists()) {
                throw new RuntimeException("folder not find Exception");
            }
            OutputStream os = new FileOutputStream(new File(destFileName));
            ZipOutputStream zos = new ZipOutputStream(os);
            BufferedOutputStream bo = new BufferedOutputStream(zos);
            zipFileOrFolder(zos, bo, "", folder);
            zos.close();
            bo.close();
            System.out.println("压缩完成>>>>>>>>>>");
        }
    
        /**
         * 将目录下所有的文件和子文件都压缩到zos中
         * @param zos
         * @param bo
         * @param src
         * @param f
         * @throws IOException
         */
        private static void zipFileOrFolder(ZipOutputStream zos, BufferedOutputStream bo, String src, File f) throws IOException {
            File[] files;
            if (f.isDirectory()) {
                files = f.listFiles();
                assert files != null;
                System.out.println("========== " + f.getName());
    //添加文件夹的entry,不添加的话,解压时会出问题。 zos.putNextEntry(new ZipEntry( src+f.getName()+"/" )); System.out.println( src+f.getName()+"/" ); src = src+f.getName() + "/"; for (File f1 : files) {
    //使用了递归调用获取下一层文件夹并压缩 zipFileOrFolder(zos, bo, src, f1); } } else { System.out.println("---------- " + f.getName()); InputStream in = new FileInputStream(f); BufferedInputStream bi = new BufferedInputStream(in); zos.putNextEntry(new ZipEntry( src+f.getName() )); int b; while ((b = bi.read()) != -1) { bo.write(b); } bo.flush(); bi.close(); zos.closeEntry(); } } /** * 解压单个zip文件,保留文件夹层级关系 * @param zipFile * @param outPath * @throws IOException */ public static void unZip(String zipFile, String outPath) throws IOException { File zip = new File(zipFile); ZipFile zf = new ZipFile(zip); InputStream is = new FileInputStream(zipFile); ZipInputStream zis = new ZipInputStream(is); ZipEntry e; File out = new File(outPath); if (!out.exists()) { out.mkdir(); } while ((e = zis.getNextEntry()) != null) { System.out.println(e.isDirectory()); File f = new File(outPath + e.getName()); System.out.println(f.getAbsolutePath()); if(e.isDirectory()){ f.mkdir();continue; } OutputStream os = new FileOutputStream(f); BufferedOutputStream bos = new BufferedOutputStream(os); BufferedInputStream bis = new BufferedInputStream(zf.getInputStream(e)); int b; while ((b = bis.read()) != -1) { bos.write(b); } bos.flush(); bos.close(); bis.close(); } zis.close(); } public static void unZipAll(String zipFolder,String destFolder){ //todo } public static void main(String[] args) throws IOException { compressFile("D:/test/123.txt", "D:/test/a/b/", "123.zip"); unCompress("D:/test/123.zip", "D:/test/"); compressNestFolder("D:/test/测试zip/新垣结衣/", "D:/test/测试zip/新垣结衣1.zip"); unZip("D:/test/测试zip/新垣结衣1.zip", "D:/test/测试zip/"); } }

    后记:

    1.添加到zip中使用putNextEntry,从zip中读取时需要创建一个ZipFile然后从entry中获取InputStream。

    2.需要特别注意压缩文件时的Entry存放次序,在添加entry时务必先添加文件夹的entry。因为取entry时,如果乱序就会找不到文件。比如获取/bt/123.pic时,因为没有实现创建父目录/bt,导致写文件时找不到文件。

    3.对entry.isDirectory()的判断,api中是根据name是否以 / 结尾的。因此存放folder时,也要使用 / 作为路径分割符。java在windows平台上是支持 / 的,虽然windows平台上路径分隔符是  (java中是\)。建议还是用 / 吧。

    4.Zip对象存放文件是使用相对路径的,所以压缩什么的不要有盘符。添加目录时以 / 结尾,多级目录时添加文件使用完全相对路径名 /相对路径1/相对路径2/文件名,可以通过查看打印信息了解方法执行过程。

    -----------------以上-----------------

  • 相关阅读:
    get_folder_size.ps1
    python3-database-shelve
    Windows中实现不依赖账户登录的开机启动程序
    SpringBoot+SpringDataJPA如何实现自定义且自由度高的查询[多表,多查询条件,多排序条件,分页,自定义sql封装]
    Windows phone 8.1之数据绑定(Data Binding)
    TextBox使用技巧--转载
    在Eclipse中使用git把项目导入到git中--转载
    运用多种知识点实现一个综合小游戏
    Git帮助之初始化项目设置向导
    如何从Eclipse导入github上的项目源码--转载
  • 原文地址:https://www.cnblogs.com/opensesame/p/6415428.html
Copyright © 2020-2023  润新知