java生成tar.gz格式文件之归档、打包、压缩、解压缩

问题背景: 在上一篇文章中我们提到了关于 Java 打包问题,同时放上了样例代码。昨天下午登录CSDN的时候发现有同学留言请教如何取消文档打包时文件夹目录过深的问题。所以今天特来把这位同学的问题解决一下。话不多说,上代码啦~!

依赖jar包:
commons-compress-1.12.jar

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;

/**
 * 多文件压缩与解压
 * 
 * @author Supreme_Sir
 */

public class CompressUtil {
	// 符号"/"用来作为目录标识判断符
	private static final String PATH = "/";
	private static final String BASE_DIR = "";
	private final static int BUFFER = 1048576;

	/**
	 * 解压tar.gz文件
	 * 
	 * @param tar_gz
	 * @param sourceFolder
	 */
	public void decompress(File tar_gz, String sourceFolder) {
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		GZIPInputStream gzis = null;
		TarArchiveInputStream tais = null;
		OutputStream out = null;
		try {
			fis = new FileInputStream(tar_gz);
			bis = new BufferedInputStream(fis);
			gzis = new GZIPInputStream(bis);
			tais = new TarArchiveInputStream(gzis);
			TarArchiveEntry tae = null;
			boolean flag = false;
			while ((tae = tais.getNextTarEntry()) != null) {
				File tmpFile = new File(sourceFolder + tae.getName());
				if (!flag) {
					// 使用 mkdirs 可避免因文件路径过多而导致的文件找不到的异常
					new File(tmpFile.getParent()).mkdirs();
					flag = true;
				}
				out = new FileOutputStream(tmpFile);
				int length = 0;
				byte[] b = new byte[BUFFER];
				while ((length = tais.read(b)) != -1) {
					out.write(b, 0, length);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (tais != null)
					tais.close();
				if (gzis != null)
					gzis.close();
				if (bis != null)
					bis.close();
				if (fis != null)
					fis.close();
				if (out != null) {
					out.flush();
					out.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 *   将指定路径中的文件归档、打包、压缩成 .tar.gz 格式的文件
	  * @Title: compresser 
	  * @param sourcePath 要打包压缩的路径
	  * @param outPutPath 生成的 .tar.gz 文件的输出目录
	  * @param fileName 生成的 .tar.gz 文件的文件名(不用加文件类型后缀)
	  * @return    
	  * File    
	  * @throws
	 */
	public File compresser(String sourcePath, String outPutPath, String fileName) {
		File outPutFile = null;
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		GZIPOutputStream gzp = null;
		File tar = null;
		try {
			tar = pack(sourcePath);
			fis = new FileInputStream(tar);
			bis = new BufferedInputStream(fis, BUFFER);
			outPutFile = new File(outPutPath + "/" + fileName + ".tar.gz");
			fos = new FileOutputStream(outPutFile);
			gzp = new GZIPOutputStream(fos);
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = bis.read(data, 0, BUFFER)) != -1) {
				gzp.write(data, 0, count);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (gzp != null) {
					gzp.finish();
					gzp.flush();
					gzp.close();
				}
				if (fos != null)
					fos.close();
				if (bis != null)
					bis.close();
				if (fis != null)
					fis.close();
				if (tar.exists()) {
					 tar.delete();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return outPutFile;
	}

	/**
	 * 将路径中的所有内容归档打包成tar包后返回
	 * 
	  * @Title: pack 
	  * @param sourcePath 要打包压缩的路径
	  * @return
	  * @throws Exception    
	  * File    
	  * @throws
	 */
	private File pack(String sourcePath) throws Exception {
		File srcFile = new File(sourcePath);
		String name = srcFile.getName();
		String basePath = srcFile.getParent();
		File target = new File(basePath + name + ".tar");
		TarArchiveOutputStream taos = new TarArchiveOutputStream(new FileOutputStream(target));
		//解决文件名过长问题
        taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
		archive(srcFile, taos, BASE_DIR);
		taos.flush();
		taos.close();
		return target;
	}

	// 根据类型进行归档函数调用
	private void archive(File srcFile, TarArchiveOutputStream taos, String basePath) throws Exception {
		if (srcFile.isDirectory()) {
			archiveDir(srcFile, taos, basePath);
		} else {
			archiveFile(srcFile, taos, basePath);
		}
	}
	
	// 文件归档
    private void archiveFile(File file, TarArchiveOutputStream taos,  String dir) throws Exception {
        TarArchiveEntry entry = new TarArchiveEntry(dir + file.getName());
        entry.setSize(file.length());
        taos.putArchiveEntry(entry);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        int count;
        byte data[] = new byte[BUFFER];
        while ((count = bis.read(data, 0, BUFFER)) != -1) {
            taos.write(data, 0, count);
        }
        bis.close();
        taos.closeArchiveEntry();
    }

    // 目录递归归档
    private void archiveDir(File dir, TarArchiveOutputStream taos, String basePath) throws Exception {
		File[] files = dir.listFiles();
		if (files.length < 1) {
			TarArchiveEntry entry = new TarArchiveEntry(basePath + dir.getName() + PATH);
			taos.putArchiveEntry(entry);
			taos.closeArchiveEntry();
		}
		for (File file : files) {
			archive(file, taos, basePath + dir.getName() + PATH);
		}
	}
	
    // 测试
	public static void main(String[] args) {
		CompressUtil util= new CompressUtil();
		util.decompress(util.compresser("E:/applogs/A/B/logs", "E:/", "OK"), "E:/");
	}
}

建议:
当进行主函数功能测试的时,将文件目录层级进行多级嵌套更能体会到本文与上一篇文章的不同哦~!

你可能感兴趣的:(后台)