这篇文章主要讲解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();

            }

        }

    }

———————————–

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

https://blog.51cto.com/u_296714/5586464