Java 7z 磁盘压缩实现

  7z是一种主流高效的压缩格式,拥有极高的压缩比。7z是一种可以使用多种压缩算法进行数据压缩的档案格式。通常使用7z格式能比zip格式的压缩文件小20%-70%,但是在时间和空间上需要更大的消耗。

  7z已公开了结构编辑功能,所以它可以支持任何一种新的压缩算法。到目前为止,下列压缩算法已被整合到了 7z中:

压缩算法 备注
LZMA 改良与优化后的LZ77算法
LZMA2 改良的LZMA算法
PPMD 基于Dmitry ShkarinDE PPMdH算法
BCJ 32位x86可执行文件转换程序
BCJ2 32位x86可执行文件转换程序
BZip2 标准BWT算法
Deflate 标准LZ77-based算法

  关于7z的算法介绍及特征等描述信息,可以自行百度查看。

  本文针对磁盘上进行压缩和解压演示,演示只针对一层目录结构进行,多层目录只需递归操作进行即可。

  · Maven依赖

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-compress</artifactId>
	<version>1.19</version>
</dependency>
<dependency>
    <groupId>org.tukaani</groupId>
    <artifactId>xz</artifactId>
    <version>1.8</version>
</dependency>

  · 磁盘压缩和解压

  无特殊情况下,操作都是在磁盘上进行,将所有文件存放在某一目录中,然后对目录进行压缩,工具类代码如下:

package com.arhorchin.securitit.compress.sevenz;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;

public class SevenZDiskUtil {

    /**
     * 7z 压缩.
     * @param srcDirPath 待压缩目录.
     * @param tarFilePath 压缩文件路径.
     * @throws Exception .
     */
    public static void sevenZCompress(String srcDirPath, String tarFilePath) throws Exception {
        SevenZArchiveEntry archiveEntry = null;
        File sevenZFile = null;
        File seveZTarFile = null;
        SevenZOutputFile sevenZOutputFile = null;
        File[] sevenZFileList = null;
        FileInputStream sevenZFis = null;
        BufferedInputStream sevenBis = null;

        try {
            sevenZFile = new File(srcDirPath);
            seveZTarFile = new File(tarFilePath);
            sevenZOutputFile = new SevenZOutputFile(seveZTarFile);
            sevenZFileList = sevenZFile.listFiles();
            if (null == sevenZFileList || sevenZFileList.length <= 0) {
                return;
            }
            for (File file : sevenZFileList) {
                sevenZFis = new FileInputStream(file);
                sevenBis = new BufferedInputStream(sevenZFis);
                archiveEntry = sevenZOutputFile.createArchiveEntry(file, file.getName());
                sevenZOutputFile.putArchiveEntry(archiveEntry);
                int len = -1;
                // 将源文件写入到7z文件中.
                byte[] buf = new byte[1024];
                while ((len = sevenBis.read(buf)) != -1) {
                    sevenZOutputFile.write(buf, 0, len);
                }
            }
            sevenBis.close();
            sevenZFis.close();
            sevenZOutputFile.closeArchiveEntry();
        } finally {
            if (null != sevenBis) {
                sevenBis.close();
            }
            if (null != sevenZFis) {
                sevenZFis.close();
            }
            if (null != sevenZOutputFile) {
                sevenZOutputFile.close();
            }
        }
    }

    /**
     * 7z 解压.
     * @param srcFilePath 待解压文件路径.
     * @param tarDirPath 解压后文件目录.
     * @throws Exception .
     */
    public static void sevenZDecompress(String srcFilePath, String tarDirPath) throws Exception {
        SevenZArchiveEntry archiveEntry = null;
        File sevenZSrcFile = null;
        SevenZFile sevenZFile = null;
        OutputStream sevenZOs = null;
        OutputStream sevenZBos = null;

        try {
            sevenZSrcFile = new File(srcFilePath);
            // 针对压缩文件开始解压.
            sevenZFile = new SevenZFile(sevenZSrcFile);
            File file = null;
            while ((archiveEntry = sevenZFile.getNextEntry()) != null) {
                if (!archiveEntry.isDirectory()) {
                    file = new File(tarDirPath, archiveEntry.getName());
                    // 创建此文件的上级目录.
                    if (!file.exists()) {
                        new File(file.getParent()).mkdirs();
                    }
                    sevenZOs = new FileOutputStream(file);
                    sevenZBos = new BufferedOutputStream(sevenZOs);
                    int len = -1;
                    byte[] buf = new byte[1024];
                    while ((len = sevenZFile.read(buf)) != -1) {
                        sevenZOs.write(buf, 0, len);
                    }
                }
            }
        } finally {
            if (null != sevenZOs) {
                sevenZOs.close();
            }
            if (null != sevenZBos) {
                sevenZBos.close();
            }
            if (null != sevenZFile) {
                sevenZFile.close();
            }
        }
    }

}

  测试代码如下:

package com.arhorchin.securitit.com.compress;

import com.arhorchin.securitit.compress.sevenz.SevenZDiskUtil;

public class SevenZDiskUtilTester {

    public static void main(String[] args) throws Exception {
        String srcDirPath = "C:/Users/Administrator/Downloads/个人文件/7z-test";
        String tarFilePath = "C:/Users/Administrator/Downloads/个人文件/7z-test.7z";
        
        SevenZDiskUtil.sevenZCompress(srcDirPath, tarFilePath);
        
        String srcFilePath = "C:/Users/Administrator/Downloads/个人文件/7z-test.7z";
        String tarSrcPath = "C:/Users/Administrator/Downloads/个人文件/7z-test-de";
        SevenZDiskUtil.sevenZDecompress(srcFilePath, tarSrcPath);
    }
    
}

  · 总结

  使用7z压缩格式可以取得更高的压缩比,当然,任何事情发生都是有前提的,在对不同类型或不同内容文件进行压缩时,压缩比会存在变动,并不会一直稳定在某个水准。总的来说,抛开条件谈性能、谈效率,都是耍流氓。在传输或存储时,对文件大小有要求的场景下,可以使用此种压缩格式。但同时也要注意7z高压缩比所带来的负面影响,以便在系统或功能设计时,可以提前预知风险且提早进行风险防控。

猜你喜欢

转载自blog.csdn.net/securitit/article/details/107441513