当前位置: 移动技术网 > IT编程>开发语言>Java > Java GZip 基于磁盘实现压缩和解压的方法

Java GZip 基于磁盘实现压缩和解压的方法

2020年08月23日  | 移动技术网IT编程  | 我要评论
  gzip是常用的无损压缩算法实现,在linux中较为常见,像我们在linux安装软件时,基本都是.tar.gz格式。.tar.gz格式文件需要先对目录内文件进行tar压缩,

  gzip是常用的无损压缩算法实现,在linux中较为常见,像我们在linux安装软件时,基本都是.tar.gz格式。.tar.gz格式文件需要先对目录内文件进行tar压缩,然后使用gzip进行压缩。

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

  maven依赖

  org.apache.commons: commons-compress: 1.19: 此依赖封装了很多压缩算法相关的工具类,提供的api还是相对比较底层,我们今天在它的基础上做进一步封装。

<dependency>
	<groupid>org.apache.commons</groupid>
	<artifactid>commons-compress</artifactid>
	<version>1.19</version>
</dependency>
<dependency>
 <groupid>log4j</groupid>
 <artifactid>log4j</artifactid>
 <version>1.2.17</version>
</dependency>

  工具类

  其实,在通常情况下,我们都是在磁盘上进行压缩和解压操作的,这样虽然增加了操作的复杂度,但是却无形中避免了一些问题。

  工具类针对.tar.gz格式提供了compressbytar、decompressbytar、compressbygzip、decompressbygzip四个方法,用于处理.tar.gz格式压缩文件,代码如下:

package com.arhorchin.securitit.compress.gzip;

import java.io.bufferedinputstream;
import java.io.bufferedoutputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.fileoutputstream;
import java.io.ioexception;

import org.apache.commons.compress.archivers.tar.tararchiveentry;
import org.apache.commons.compress.archivers.tar.tararchiveinputstream;
import org.apache.commons.compress.archivers.tar.tararchiveoutputstream;
import org.apache.commons.compress.compressors.gzip.gzipcompressorinputstream;
import org.apache.commons.compress.compressors.gzip.gzipcompressoroutputstream;
import org.apache.commons.compress.utils.ioutils;
import org.apache.log4j.logger;

/**
 * @author securitit.
 * @note 基于磁盘以gzip算法进行压缩和解压工具类.
 */
public class gzipdiskutil {

 /**
 * logger.
 */
 private static logger logger = logger.getlogger(gzipdiskutil.class);

 /**
 * utf-8字符集.
 */
 public static string charset_utf8 = "utf-8";

 /**
 * 使用tar算法进行压缩.
 * @param sourcefolderpath 待进行压缩的文件夹路径.
 * @param targettarfilepath 压缩后的tar文件存储目录.
 * @return 压缩是否成功.
 * @throws exception 压缩过程中可能发生的异常.
 */
 public static boolean compressbytar(string sourcefolderpath, string targettarfilepath) throws exception {
 // 变量定义.
 file sourcefolderfile = null;
 fileoutputstream targettarfos = null;
 tararchiveoutputstream targettarttaos = null;
 tararchiveentry targettartae = null;

 try {
  // 压缩变量初始化.
  sourcefolderfile = new file(sourcefolderpath);
  targettarfos = new fileoutputstream(new file(targettarfilepath));
  targettarttaos = new tararchiveoutputstream(targettarfos);
  // 将文件添加到zip条目中.
  for (file file : sourcefolderfile.listfiles()) {
  try (fileinputstream fis = new fileinputstream(file);
   bufferedinputstream bis = new bufferedinputstream(fis);) {
   targettartae = new tararchiveentry(file);
   targettartae.setname(file.getname());
   targettarttaos.putarchiveentry(targettartae);
   targettarttaos.write(ioutils.tobytearray(bis));
   targettarttaos.closearchiveentry();
  }
  }
 } catch (exception ex) {
  logger.info("gzipdiskutil.compressbytar.", ex);
  return false;
 } finally {
  if (targettarttaos != null)
  targettarttaos.close();
  if (targettarfos != null)
  targettarfos.close();

 }
 return true;
 }

 /**
 * 使用tar算法进行解压.
 * @param sourcetarpath 待解压文件路径.
 * @param targetfolderpath 解压后文件夹目录.
 * @return 解压是否成功.
 * @throws exception 解压过程中可能发生的异常.
 */
 public static boolean decompressbytar(string sourcetarpath, string targetfolderpath) throws exception {
 // 变量定义.
 fileinputstream sourcetarfis = null;
 tararchiveinputstream sourcetartais = null;
 tararchiveentry sourcetartae = null;
 file singleentryfile = null;

 try {
  // 解压定义初始化.
  sourcetarfis = new fileinputstream(new file(sourcetarpath));
  sourcetartais = new tararchiveinputstream(sourcetarfis);
  // 条目解压缩至指定文件夹目录下.
  while ((sourcetartae = sourcetartais.getnexttarentry()) != null) {
  singleentryfile = new file(targetfolderpath + file.separator + sourcetartae.getname());
  try (fileoutputstream fos = new fileoutputstream(singleentryfile);
   bufferedoutputstream bos = new bufferedoutputstream(fos);) {
   bos.write(ioutils.tobytearray(sourcetartais));
  }
  }
 } catch (exception ex) {
  logger.info("gzipdiskutil.decompressbytar.", ex);
  return false;
 } finally {
  if (sourcetartais != null)
  sourcetartais.close();
  if (sourcetarfis != null)
  sourcetarfis.close();
 }
 return true;
 }

 /**
 * 使用gzip算法进行压缩.
 * @param sourcefilepath 待进行压缩的文件路径.
 * @param targetgzipfilepath 压缩后的gzip文件存储目录.
 * @return 压缩是否成功.
 * @throws exception 压缩过程中可能发生的异常.
 */
 public static boolean compressbygzip(string sourcefilepath, string targetgzipfilepath) throws ioexception {
 // 变量定义.
 fileinputstream sourcefilefis = null;
 bufferedinputstream sourcefilebis = null;
 fileoutputstream targetgzipfilefos = null;
 bufferedoutputstream targetgzipfilebos = null;
 gzipcompressoroutputstream targetgzipfilegcos = null;

 try {
  // 压缩变量初始化.
  sourcefilefis = new fileinputstream(new file(sourcefilepath));
  sourcefilebis = new bufferedinputstream(sourcefilefis);
  targetgzipfilefos = new fileoutputstream(targetgzipfilepath);
  targetgzipfilebos = new bufferedoutputstream(targetgzipfilefos);
  targetgzipfilegcos = new gzipcompressoroutputstream(targetgzipfilebos);
  // 采用commons-compress提供的方式进行压缩.
  targetgzipfilegcos.write(ioutils.tobytearray(sourcefilebis));
 } catch (exception ex) {
  logger.info("gzipdiskutil.compressbygzip.", ex);
  return false;
 } finally {
  if (targetgzipfilegcos != null)
  targetgzipfilegcos.close();
  if (targetgzipfilebos != null)
  targetgzipfilebos.close();
  if (targetgzipfilefos != null)
  targetgzipfilefos.close();
  if (sourcefilebis != null)
  sourcefilebis.close();
  if (sourcefilefis != null)
  sourcefilefis.close();
 }
 return true;
 }

 /**
 * 使用gzip算法进行解压.
 * @param sourcegzipfilepath 待解压文件路径.
 * @param targetfilepath 解压后文件路径.
 * @return 解压是否成功.
 * @throws @throws exception 解压过程中可能发生的异常.
 */
 public static boolean decompressbygzip(string sourcegzipfilepath, string targetfilepath) throws ioexception {
 // 变量定义.
 fileinputstream sourcegzipfilefis = null;
 bufferedinputstream sourcegzipfilebis = null;
 fileoutputstream targetfilefos = null;
 gzipcompressorinputstream sourcegzipfilegcis = null;

 try {
  // 解压变量初始化.
  sourcegzipfilefis = new fileinputstream(new file(sourcegzipfilepath));
  sourcegzipfilebis = new bufferedinputstream(sourcegzipfilefis);
  sourcegzipfilegcis = new gzipcompressorinputstream(sourcegzipfilebis);
  targetfilefos = new fileoutputstream(new file(targetfilepath));
  // 采用commons-compress提供的方式进行解压.
  targetfilefos.write(ioutils.tobytearray(sourcegzipfilegcis));
 } catch (exception ex) {
  logger.info("gzipdiskutil.decompressbygzip.", ex);
  return false;
 } finally {
  if (sourcegzipfilegcis != null)
  sourcegzipfilegcis.close();
  if (sourcegzipfilebis != null)
  sourcegzipfilebis.close();
  if (sourcegzipfilefis != null)
  sourcegzipfilefis.close();
  if (targetfilefos != null)
  targetfilefos.close();
 }
 return true;
 }

}

工具类测试

  在maven依赖引入正确的情况下,复制上面的代码到项目中,修改package,可以直接使用,下面我们对工具类进行简单测试。测试类代码如下:

package com.arhorchin.securitit.compress.gzip;

import com.arhorchin.securitit.compress.gzip.gzipdiskutil;

/**
 * @author securitit.
 * @note gzipdiskutil工具类测试.
 */
public class gzipdiskutiltester {

 public static void main(string[] args) throws exception {
 gzipdiskutil.compressbytar("c:/users/administrator/downloads/个人文件/2020-07-13/files", "c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar");
 gzipdiskutil.compressbygzip("c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar", "c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar.gz");
 
 gzipdiskutil.decompressbygzip("c:/users/administrator/downloads/个人文件/2020-07-13/disk.tar.gz", "c:/users/administrator/downloads/个人文件/2020-07-13/disk-untar.tar");
 gzipdiskutil.decompressbytar("c:/users/administrator/downloads/个人文件/2020-07-13/disk-untar.tar", "c:/users/administrator/downloads/个人文件/2020-07-13/disk-untar");
 }

}

  运行测试后,通过查看disk.tar、disk.tar.gz、disk-untar.tar和解压的目录,可以确认工具类运行结果无误。

总结

  1) 在小文件、文件数量较小且较为固定时,提倡使用内存压缩和解压方式。使用内存换时间,减少频繁的磁盘操作。《java gzip 基于内存实现压缩和解压

  2) 在大文件、文件数量较大时,提倡使用磁盘压缩和解压方式。过大文件对服务会造成过度的负载,磁盘压缩和解压可以缓解这种压力。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网