• Java压缩技术之解压篇,支持:ZIP、RAR、7Z、TAR、GZ、TAR.GZ、BZ2、TAR.BZ2


    转载自:https://blog.csdn.net/qq_28082757/article/details/78932756

    这篇文章主要讲解Java解压的操作,后续会写一篇关于压缩的文章。

    提醒:文章中有些片段看似代码很多,其实去除trycatch、释放资源真正有用的代码没几句,解压其实都很简单,主要用心去观察,都是依葫芦画瓢。

    首先,先写一个类似辅助的视图类:

    public enum FileType {
        // 未知
        UNKNOWN,
        // 压缩文件
        ZIP, RAR, _7Z, TAR, GZ, TAR_GZ, BZ2, TAR_BZ2,
        // 位图文件
        BMP, PNG, JPG, JPEG,
        // 矢量图文件
        SVG,
        // 影音文件
        AVI, MP4, MP3, AAR, OGG, WAV, WAVE
    }

    这个类主要是用来将各种文件的类型集中管理,当然,不写这个类也是可以的,可以直接用字符串去表示。

    然后,我还写了一个获取文件真实类型的方法,为什么要写这个方法呢?因为,我们是可以直接去修改文件的后缀的,这样很危险!

    本博客博主按:根据文件头检测文件类型+文件扩展名是比较严谨的办法。

    但是一些特殊情况可能是例外:例如千千静听,等软件皮肤是zip文件,openoffice格式文件也是zip压缩的,尽管他是xlsx格式的

       /**
         * 获取文件真实类型
         *
         * @param file 要获取类型的文件。
         * @return 文件类型枚举。
         */
        private static FileType getFileType(File file){
            FileInputStream inputStream =null;
            try{
                inputStream = new FileInputStream(file);
                byte[] head = new byte[4];
                if (-1 == inputStream.read(head)) {
                    return FileType.UNKNOWN;
                }
                int headHex = 0;
                for (byte b : head) {
                    headHex <<= 8;
                    headHex |= b;
                }
                switch (headHex) {
                    case 0x504B0304:
                        return FileType.ZIP;
                    case 0x776f7264:
                        return FileType.TAR;
                    case -0x51:
                        return FileType._7Z;
                    case 0x425a6839:
                        return FileType.BZ2;
                    case -0x74f7f8:
                        return FileType.GZ;
                    case 0x52617221:
                        return FileType.RAR;
                    default:
                        return FileType.UNKNOWN;
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try {
                    if(inputStream!=null){
                        inputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return FileType.UNKNOWN;
        }

    这里是通过文件头信息来判断什么类型的。其他文件的头文件信息,这里就不展示了。如果有需要,可以拿文件来跑跑,看看headHex是啥值就行了。

    最后还有一个创建目录的辅助方法:

       /**
         *  构建目录
         * @param outputDir 输出目录
         * @param subDir 子目录
         */
        private static void createDirectory(String outputDir, String subDir){
            File file = new File(outputDir);
            if(!(subDir == null || subDir.trim().equals(""))) {//子目录不为空
                file = new File(outputDir + File.separator + subDir);
            }
            if(!file.exists()){
                if(!file.getParentFile().exists()){
                    file.getParentFile().mkdirs();
                }
                file.mkdirs();
            }
        }

    tar文件解压

    接下来是正儿八经的正菜了。第一个来看怎么解压tar文件。
    好在解压tar文件的工具JDK自带了~下面看代码:

        /**
         * 解压缩tar文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        private static void decompressTar(File file, String targetPath, boolean delete){
            FileInputStream fis = null;
            OutputStream fos = null;
            TarInputStream tarInputStream = null;
            try {
                fis = new FileInputStream(file);
                tarInputStream = new TarInputStream(fis, 1024 * 2);
                // 创建输出目录
                createDirectory(targetPath, null);
    
                TarEntry entry = null;
                while(true){
                    entry = tarInputStream.getNextEntry();
                    if( entry == null){
                        break;
                    }
                    if(entry.isDirectory()){
                        createDirectory(targetPath, entry.getName()); // 创建子目录
                    }else{
                        fos = new FileOutputStream(new File(targetPath + File.separator + entry.getName()));
                        int count;
                        byte data[] = new byte[2048];
                        while ((count = tarInputStream.read(data)) != -1) {
                            fos.write(data, 0, count);
                        }
                        fos.flush();
                    }
                }
            } catch (IOException e) {
               e.printStackTrace();
            }finally {
                try {
                    if(fis != null){
                        fis.close();
                    }
                    if(fos != null){
                        fos.close();
                    }
                    if(tarInputStream != null){
                        tarInputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    有一点需要注意的是:方法参数传了一个是否需要删除原压缩包的参数,如果需要删除的话,必须必须必须等到流关闭了之后才能删除,不然是删不掉的。也可以在该方法的调用者那里删,这样就可以不用传这个参数了。

    bz2文件解压

    解压bz2文件我这里是用的Apache的commons.compress工具来解压,先下载jar包:commons-compress-1.9.jar,(1.8的貌似有问题,我就换成了1.9)

        /**
         * 解压缩bz2文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        public static void decompressBZ2(File file, String targetPath, boolean delete){
            FileInputStream fis = null;
            OutputStream fos = null;
            BZip2CompressorInputStream bis = null;
            String suffix = ".bz2";
            try {
                fis = new FileInputStream(file);
                bis = new BZip2CompressorInputStream(fis);
                // 创建输出目录
                createDirectory(targetPath, null);
                File tempFile = new File(targetPath + File.separator + file.getName().replace(suffix, ""));
                fos = new FileOutputStream(tempFile);
    
                int count;
                byte data[] = new byte[2048];
                while ((count = bis.read(data)) != -1) {
                    fos.write(data, 0, count);
                }
                fos.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if(fis != null){
                        fis.close();
                    }
                    if(fos != null){
                        fos.close();
                    }
                    if(bis != null){
                        bis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    tar.bz2文件解压

        /**
         * 解压缩tar.bz2文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        public static void decompressTarBz2(File file, String targetPath, boolean delete){
            FileInputStream fis = null;
            OutputStream fos = null;
            BZip2CompressorInputStream bis = null;
            TarInputStream tis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BZip2CompressorInputStream(fis);
                tis = new TarInputStream(bis, 1024 * 2);
                // 创建输出目录
                createDirectory(targetPath, null);
                TarEntry entry;
                while((entry = tis.getNextEntry()) != null){
                    if(entry.isDirectory()){
                        createDirectory(targetPath, entry.getName()); // 创建子目录
                    }else{
                        fos = new FileOutputStream(new File(targetPath + File.separator + entry.getName()));
                        int count;
                        byte data[] = new byte[2048];
                        while ((count = tis.read(data)) != -1) {
                            fos.write(data, 0, count);
                        }
                        fos.flush();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if(fis != null){
                        fis.close();
                    }
                    if(fos != null){
                        fos.close();
                    }
                    if(bis != null){
                        bis.close();
                    }
                    if(tis != null){
                        tis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    tar.gz文件解压

        /**
         * 解压缩tar.gz文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        private static void decompressTarGz(File file, String targetPath,  boolean delete){
            FileInputStream  fileInputStream = null;
            BufferedInputStream bufferedInputStream = null;
            GZIPInputStream gzipIn = null;
            TarInputStream tarIn = null;
            OutputStream out = null;
            try {
                fileInputStream = new FileInputStream(file);
                bufferedInputStream = new BufferedInputStream(fileInputStream);
                gzipIn = new GZIPInputStream(bufferedInputStream);
                tarIn = new TarInputStream(gzipIn, 1024 * 2);
    
                // 创建输出目录
                createDirectory(targetPath, null);
    
                TarEntry entry = null;
                while((entry = tarIn.getNextEntry()) != null){
                    if(entry.isDirectory()){ // 是目录
                        createDirectory(targetPath, entry.getName()); // 创建子目录
                    }else{ // 是文件
                        File tempFIle = new File(targetPath + File.separator + entry.getName());
                        createDirectory(tempFIle.getParent() + File.separator, null);
                        out = new FileOutputStream(tempFIle);
                        int len =0;
                        byte[] b = new byte[2048];
    
                        while ((len = tarIn.read(b)) != -1){
                            out.write(b, 0, len);
                        }
                        out.flush();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if(out != null){
                        out.close();
                    }
                    if(tarIn != null){
                        tarIn.close();
                    }
                    if(gzipIn != null){
                        gzipIn.close();
                    }
                    if(bufferedInputStream != null){
                        bufferedInputStream.close();
                    }
                    if(fileInputStream != null){
                        fileInputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    gz文件解压

        /**
         * 解压缩gz文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        private static void decompressGz(File file, String targetPath,  boolean delete){
            FileInputStream  fileInputStream = null;
            GZIPInputStream gzipIn = null;
            OutputStream out = null;
            String suffix = ".gz";
            try {
                fileInputStream = new FileInputStream(file);
                gzipIn = new GZIPInputStream(fileInputStream);
                // 创建输出目录
                createDirectory(targetPath, null);
    
                File tempFile = new File(targetPath + File.separator + file.getName().replace(suffix, ""));
                out = new FileOutputStream(tempFile);
                int count;
                byte data[] = new byte[2048];
                while ((count = gzipIn.read(data)) != -1) {
                    out.write(data, 0, count);
                }
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if(out != null){
                        out.close();
                    }
                    if(gzipIn != null){
                        gzipIn.close();
                    }
                    if(fileInputStream != null){
                        fileInputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    7z文件解压

        /**
         * 解压缩7z文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        private static void decompress7Z(File file, String targetPath,  boolean delete){
            SevenZFile sevenZFile = null;
            OutputStream outputStream = null;
            try {
                sevenZFile = new SevenZFile(file);
                // 创建输出目录
                createDirectory(targetPath, null);
                SevenZArchiveEntry entry;
    
                while((entry = sevenZFile.getNextEntry()) != null){
                    if(entry.isDirectory()){
                        createDirectory(targetPath, entry.getName()); // 创建子目录
                    }else{
                        outputStream = new FileOutputStream(new File(targetPath + File.separator + entry.getName()));
                        int len = 0;
                        byte[] b = new byte[2048];
                        while((len = sevenZFile.read(b)) != -1){
                            outputStream.write(b, 0, len);
                        }
                        outputStream.flush();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if(sevenZFile != null){
                        sevenZFile.close();
                    }
                    if(outputStream != null){
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    rar文件解压

    先下载jar包:junrar-0.7.jar、xz-1.5.jar、commons-logging.jar

    /**
         * 解压缩RAR文件
         * @param file 压缩包文件
         * @param targetPath 目标文件夹
         * @param delete 解压后是否删除原压缩包文件
         */
        private static void decompressRAR(File file, String targetPath,  boolean delete){
            Archive archive = null;
            OutputStream outputStream = null;
            try {
                archive = new Archive(file);
                FileHeader fileHeader;
                // 创建输出目录
                createDirectory(targetPath, null);
                while( (fileHeader = archive.nextFileHeader()) != null){
                    if(fileHeader.isDirectory()){
                        createDirectory(targetPath, fileHeader.getFileNameString().trim()); // 创建子目录
                    }else{
                        outputStream = new FileOutputStream(new File(targetPath + File.separator + fileHeader.getFileNameString().trim()));
                        archive.extractFile(fileHeader, outputStream);
                    }
                }
            } catch (RarException | IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if(archive != null){
                        archive.close();
                    }
                    if(outputStream != null){
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
  • 相关阅读:
    Monggodb基础
    手游运营数据指标
    JSON语法
    Java中日期转换问题
    Java线程中锁的问题
    鼠标移动监听的注意事项
    链接数据库的问题
    获取显示器的宽高
    JTable的使用问题
    JScrollPane控件中添加其他控件的问题&&JScrollPane设置滚动条&&调整滚动速度
  • 原文地址:https://www.cnblogs.com/passedbylove/p/11424888.html
Copyright © 2020-2023  润新知