[重学Java基础][Java IO流][Exter.1]Apache Commonms Compress压缩工具包

Apache Commons Compress

简介

Apache Commons Copress是 Apache Commons系列工具的一个部分
是一个提供了更丰富的压缩功能和支持更多压缩格式的工具包

前面我们可知 Java自带对zip,gzip,jar格式的压缩文件支持
如果我们要处理7z,tar,bzip等格式
或者使用LZ4,Snappy等其他压缩算法
就可以使用 Apache Compress
因为rar压缩算法不公开 所以Apache Compress未提供支持

使用

压缩流工厂

压缩流工厂是最基础的压缩流创建工具 用于创建一个输入/输出流进行压缩/解压缩

  • 创建一个压缩输出流
    第一参数是CompressorStreamFactory.GZIP 所以是GZIP压缩流
    如果指定为其他格式 则为其他格式压缩流
CompressorOutputStream gzippedOut = new CompressorStreamFactory()
    .createCompressorOutputStream(CompressorStreamFactory.GZIP, myOutputStream);
  • 创建一个解压缩输入流
CompressorInputStream input = new CompressorStreamFactory()
    .createCompressorInputStream(originalInput);
  • 创建一个文档输入流
ArchiveInputStream input = new ArchiveStreamFactory()
    .createArchiveInputStream(originalInput);

文档输入流ArchiveInputStream和解压缩输入流 CompressorInputStream的区别是
ArchiveInputStream是文档输入流 用于处理归档格式文件 用于处理ZIP,JAR,AR,CPIO,ARJ,7Z,TAR
等归档型包文件
CompressorInputStream是解压缩输入流 用于处理BZIP2,GZIP,PACK200,SNAPPY_FRAMED,
Z,DEFLATE,XZ,LZMA,LZ4_FRAMED,ZSTANDARD压缩型包文件

处理文件 格式
ArchiveInputStream 归档型包 ZIP,JAR,AR,CPIO,ARJ,7Z,TAR……
CompressorInputStream 压缩型包 BZIP2,GZIP,PACK200,SNAPPY_FRAMED……

解压缩文件 通用流程

  • 核心就是ArchiveInputStream
 ArchiveInputStream input = new ArchiveStreamFactory()
                .createArchiveInputStream(new BufferedInputStream(new FileInputStream("F:/zipoutput.zip")));
构建的ArchiveInputStream 必须使用支持mark标记的流作为底层流 否则会抛出不支持标记异常
所以这里使用了BufferedInputStream 包装FileInputStream

        File targetDir = new File("F:\\uncompress");
        此处使用了try with resource(Java 7特性) 可以自动关闭流
        try (ArchiveInputStream i = input) {
            ArchiveEntry entry = null;
            while ((entry = i.getNextEntry()) != null) {
                if (!i.canReadEntryData(entry)) {
                     不能读取 或不支持的格式 算法 跳过此文件
                    continue;
                } 
                文件名 用于下面文件File类型的参数 所以需要设定全路径 
                此处为F:\uncompress\+文件名
                String name = targetDir + File.separator + entry.getName();
                File f = new File(name);
                if (entry.isDirectory()) {
                    if (!f.isDirectory() && !f.mkdirs()) {
                        throw new IOException
                        ("failed to create directory " + f);
                    }
                } else {
                    File parent = f.getParentFile();
                    if (!parent.isDirectory() && !parent.mkdirs()) {
                        throw new IOException
                        ("failed to create directory " + parent);
                    }
                    输出到目标文件 此处调用的是Java NIO
                    的Files工具类的ewOutputStream方法
                    try (OutputStream o = Files.newOutputStream(f.toPath())) {
                        IOUtils.copy(i, o);
                    }
                }
            }
        }
  • 从一个压缩型文件包解压
// 此处使用了NIO的文件输入流创建方式 因为NIO流是不支持标记和重置的
所以又使用了BufferedInputStream包装文件输入流
输入的文件格式是已知的tar.gz型 所以直接指定GzipCompressorInputStream为处理流
gzip处理流上又套接一层TarArchiveInputStream处理解压后的tar归档包文件
try (InputStream fi = new Files.newInputStream(Paths.get("my.tar.gz"));
     InputStream bi = new BufferedInputStream(fi);
     InputStream gzi = new GzipCompressorInputStream(bi);
     ArchiveInputStream o = new TarArchiveInputStream(gzi)) {
}

打包文件 通用流程

  • 核心是ArchiveOutputStream 类似JDK中提供的ZipOutputStream
    与归档文件输入流不同 ArchiveOutputStream不支持7z压缩格式,此工具提供了SevenZOutputFile类专用于处理7z格式文件压缩
需要打包的文件
Collection<File> filesToArchive = Arrays.asList(new File("E:\\图片\\截图").listFiles());

createArchiveOutputStream()方法的第一个形参指定压缩文件格式 此处设定为tar格式
ArchiveOutputStream outputStream=new ArchiveStreamFactory()
        .createArchiveOutputStream(ArchiveStreamFactory.TAR
  ,new FileOutputStream("F:\\zipArchiveoutput.tar"));
try (ArchiveOutputStream o = outputStream) {
    for (File f : filesToArchive) {
        ArchiveEntry entry = o.createArchiveEntry(f, f.getName());
        o.putArchiveEntry(entry);
        if (f.isFile()) {
            try (InputStream i = Files.newInputStream(f.toPath())) {
                使用IOUtils工具方法进行写入
                IOUtils.copy(i, o);
            }
        }
        每写入完一个实体 必须关闭这个实体 
        o.closeArchiveEntry();
    }
    压缩完毕
    此处和JDK的ZipOutputStream的finsh()方法不一样 
    ZipOutputStream是自动关闭所有未关闭实体的
    而Apache compress必须手动关闭实体
    outputStream.finish();
}

7z文件

压缩和解压缩7z文件 必须要手动添加依赖 ## XZ For Java
Apache compress反正是没有引用这个依赖包
官方文档只提示了使用一些特殊算法是需要引入此依赖
但实际上压缩7z文件必须引入依赖 如果不手动引入就会抛出未找到类异常

Gradle引入

compile group: 'org.tukaani', name: 'xz', version: '1.8'
  • 打包7z文件
    代码上大同小异
   Collection<File> filesTo7z = Arrays.asList(new File("E:\\图片\\B站截图").listFiles());

        try (SevenZOutputFile sevenZOutputFile = new SevenZOutputFile
                (new File("F:\\7zoutput."+ArchiveStreamFactory.SEVEN_Z))) {
            设置压缩算法 默认是LZMA2 通常用默认的即可
            sevenZOutputFile.setContentCompression(SevenZMethod.LZMA2);
            for (File file : filesTo7z) {
                创建压缩实体
                SevenZArchiveEntry entry = sevenZOutputFile
                .createArchiveEntry(file, file.getName());
                放入压缩文件 和其他几种压缩流基本一致的操作
                sevenZOutputFile.putArchiveEntry(entry);
                try (FileInputStream fis = new FileInputStream(file)) {
                    byte[] bytes=new byte[4096];
                    int len=-1;
                    while ((len = fis.read(bytes)) != -1) {
                        sevenZOutputFile.write(bytes,0,len);
                    }
                }
                sevenZOutputFile.closeArchiveEntry();
            }
        }
  • 解压缩7z文件
    从文件解压
        SevenZFile sevenZFile = new SevenZFile(new File("F:\\7zoutput.7z"));
        for (SevenZArchiveEntry entry : sevenZFile.getEntries()) {
            try (FileOutputStream fous = new FileOutputStream("F:\\uncompress\\" + entry.getName())) {
                每次要读入文件时 必须调用getNextEntry()方法 
                此时才会真正的打开输入流 否则会直接抛出越界异常
                sevenZFile.getNextEntry();
                byte[] content = new byte[4096];
                int len=-1;
                while ((len = sevenZFile.read(content)) != -1) {
                    fous.write(content,0,len);
                }
            }
        }
        sevenZFile.close();

从内存解压

       byte[] inputData=new byte[]{}; 文件在内存中的数据
        输入NIO的内存通道
        SeekableInMemoryByteChannel inMemoryByteChannel = new SeekableInMemoryByteChannel(inputData);
        构造SevenZFile 
        SevenZFile sevenZFile = new SevenZFile(inMemoryByteChannel);
        SevenZArchiveEntry entry = sevenZFile.getNextEntry();
        读取
        sevenZFile.read(); 

解压7加密文件

此构造方法的第二个参数为加密密码 此处输入密码为“secret” 
SevenZFile sevenZFile = new SevenZFile(new File("archive.7z"), "secret"..toCharArray());
解压过程和未加密文件无区别
for (SevenZArchiveEntry entry : sevenZFile.getEntries()) {
            try (FileOutputStream fous = new FileOutputStream("F:\\uncompress\\" + entry.getName())) {
                每次要读入文件时 必须调用getNextEntry()方法 
                此时才会真正的打开输入流 否则会直接抛出越界异常
                sevenZFile.getNextEntry();
                byte[] content = new byte[4096];
                int len=-1;
                while ((len = sevenZFile.read(content)) != -1) {
                    fous.write(content,0,len);
                }
            }
        }

LZ4压缩

LZ4是压缩速度和压缩效率都比较高的一种压缩文件算法

  • 压缩
InputStream in = Files.newInputStream(Paths.get("F:\\zipArchiveoutput.tar"));
OutputStream fout = Files.newOutputStream(Paths.get("F:\\zipArchiveoutput.tar.lz4"));
BufferedOutputStream out = new BufferedOutputStream(fout);
FramedLZ4CompressorOutputStream lzOut = new FramedLZ4CompressorOutputStream(out);
IOUtils.copy(in,lzOut);
lzOut.close();
in.close();
  • 解压缩
InputStream fin = Files.newInputStream(Paths.get("F:\\zipArchiveoutput.tar.lz4"));
BufferedInputStream in = new BufferedInputStream(fin);
OutputStream out = Files.newOutputStream(Paths.get("F:\\archive.tar"));
FramedLZ4CompressorInputStream zIn = new FramedLZ4CompressorInputStream(in);
IOUtils.copy(zIn,out);
out.close();
zIn.close();

猜你喜欢

转载自blog.csdn.net/u011863951/article/details/80549268
今日推荐