Java压缩技术的学习(tar增加非递归算法)

由于工作的需要,经常要手动去打上线安装包,为了方便,自己写程序去帮助打包。使用过Unix或者Linux的人都基本上都用过tar打包以及gzip压缩,但在Windows下使用得最多的压缩还是RAR和Zip压缩吧

一、        tar打包、解包

在java的JDK中没有原生的tar归档类,需要下载开源的包: commons-compress-1.0.jar,所以

第一步是下载jar包,可以到www.findjar.com搜索并下载。

第二步导入到工程中;忽略

第三步编写源代码,在写代码之前使用介绍一下

//打包归档输出流
org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
//解包归档输入流
org.apache.commons.compress.archivers.tar.TarArchiveInputStream
//增加打包归档的条目
void org.apache.commons.compress.archivers.tar.TarArchiveOutputStream.putArchiveEntry(ArchiveEntry arg0)
//设置归档的模式:
TarArchiveOutputStream.LONGFILE_GNU和TarArchiveOutputStream.LONGFILE_ERROR和TarArchiveOutputStream.LONGFILE_TRUNCATE
void org.apache.commons.compress.archivers.tar.TarArchiveOutputStream.setLongFileMode(int longFileMode)
//获取归档文件中的条目
TarArchiveEntry org.apache.commons.compress.archivers.tar.TarArchiveInputStream.getNextTarEntry() throws IOException

 

下面是打包的源代码:

        /**
	 * tar 打包
	 * @param source 源文件
	 * @param dest 目标文件
	 */
	public static void tar(File source){
		logger.info("开始对源文件["+source.getName()+"]打成tar包");
		FileOutputStream out = null;
		TarArchiveOutputStream tarOut = null;
		
		String parentPath = source.getParent();
		File dest = new File(parentPath + source.getName() + ".tar");
		try{
			out = new FileOutputStream(dest);
			tarOut = new TarArchiveOutputStream(out);
			//解决文件名过长
			tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
			tarPack(source, tarOut,"");
			tarOut.flush();
			tarOut.close();
			logger.info("成功把源文件打为tar包,名称为:["+dest.getName()+"]");
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}finally{
			try{
				if(out != null){
					out.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(tarOut != null){
					tarOut.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
		}
	}
	/**
	 * 归档
	 * @param source 源文件或者目录
	 * @param tarOut 归档流
	 * @param parentPath 归档后的目录或者文件路径
	 */
	public static void tarPack(File source,TarArchiveOutputStream tarOut,String parentPath){
		if(source.isDirectory()){
			tarDir(source,tarOut,parentPath);
		}else if(source.isFile()){
			tarFile(source,tarOut,parentPath);
		}
	}
	/**
	 * 归档文件(非目录)
	 * @param source 源文件
	 * @param tarOut 归档流
	 * @param parentPath 归档后的路径 
	 */
	public static void tarFile(File source,TarArchiveOutputStream tarOut,String parentPath){
		TarArchiveEntry entry = new TarArchiveEntry(parentPath + source.getName());
		BufferedInputStream bis = null;
		FileInputStream fis = null;
		try {
			entry.setSize(source.length());
			tarOut.putArchiveEntry(entry);
			fis = new FileInputStream(source);
			bis = new BufferedInputStream(fis);
			int count = -1;
			byte []buffer = new byte[1024];
			while((count = bis.read(buffer, 0, 1024)) != -1){
				tarOut.write(buffer, 0, count);
			}
			bis.close();
			tarOut.closeArchiveEntry();
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
		}finally{
			try {
				if(bis != null){
					bis.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			try {
				if(fis != null){
					fis.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	/**
	 * 归档目录
	 * @param sourceDir 原目录
	 * @param tarOut 归档流
	 * @param parentPath 归档后的父目录
	 */
	public static void tarDir(File sourceDir,TarArchiveOutputStream tarOut,String parentPath){
		//归档空目录
		if(sourceDir.listFiles().length < 1){
			TarArchiveEntry entry = new TarArchiveEntry(parentPath + sourceDir.getName() + "\\");
			try {
				tarOut.putArchiveEntry(entry);
				tarOut.closeArchiveEntry();
			} catch (IOException e) {
				logger.error(e.getMessage(),e);
			}
		}
		//递归 归档
		for (File file : sourceDir.listFiles()) {
			tarPack(file, tarOut,parentPath + sourceDir.getName() + "\\");
		}
	}

 

以下解包的源代码

/**
	 * 解归档
	 * @param source 源归档tar文件
	 */
	public static void untar(File source){
		TarArchiveInputStream tarIn = null;
		FileInputStream fis = null;
		String parentPath = source.getParent();
		
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		try{
			fis = new FileInputStream(source);
			tarIn = new TarArchiveInputStream(fis);
			TarArchiveEntry entry = null;
			while((entry = tarIn.getNextTarEntry()) != null){
				File file = new File(parentPath + "\\" + entry.getName());
              //为解决空目录
              if(entry.isDirectory()){
					file.mkdirs();
					continue;
				}
				File parentDir = file.getParentFile();
				if(!parentDir.exists()){
					parentDir.mkdirs();
				}
				
				fos = new FileOutputStream(file);
				bos = new BufferedOutputStream(fos);
				int count = -1;
				byte []buffer = new byte[1024];
				while((count = tarIn.read(buffer, 0, buffer.length)) != -1){
					bos.write(buffer, 0, count);
				}
				bos.flush();
				bos.close();
				fos.close();
			}
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}finally{
			try{
				if(fis != null){
					fis.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(fos != null){
					fos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(bos != null){
					bos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(tarIn != null){
					tarIn.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
		}
	}

 Tar的非递归算法:

/**
     * tar 打包(非递归)
     *
     * @param source 源文件
     * @param dest 目标文件
     */
    public static void tarNonRecursion(File source) {
        logger.info("开始对源文件[" + source.getName() + "]打成tar包");
        FileOutputStream out = null;
        TarArchiveOutputStream tarOut = null;

        String parentPath = source.getParent();
        File dest = new File(parentPath + "/" + source.getName() + ".tar");
        try {
            out = new FileOutputStream(dest);
            tarOut = new TarArchiveOutputStream(out, "GBK");
            //解决文件名过长
            tarOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
            Stack<File> fileStack = new Stack<File>();
            fileStack.push(source);
            File curFile;
            File preFile = null;
            while (!fileStack.empty()) {
                curFile = fileStack.peek();
                File[] fileLists = curFile.listFiles();
                if (curFile.isFile()
                        || (preFile != null && (preFile.getParent().equals(curFile.getAbsolutePath())))
                        || (fileLists.length == 0)) {
                    File popFile = fileStack.pop();
                    String filePath = popFile.getAbsolutePath();
                    filePath = filePath.replaceAll("[\\\\]", "/");
                    filePath = filePath.substring(parentPath.length() + 1);
                    preFile = curFile;
                    if (popFile.isFile()) {
                        filePath = filePath.substring(0, filePath.lastIndexOf("/"));
                        tarFile(popFile, tarOut, filePath + "/");
                    } else {
                        TarArchiveEntry entry = new TarArchiveEntry(filePath + "/");
                        try {
                            tarOut.putArchiveEntry(entry);
                            tarOut.closeArchiveEntry();
                        } catch (IOException e) {
                            logger.error(e.getMessage(), e);
                        }
                    }
                } else {
                    for (File file : fileLists) {
                        fileStack.push(file);
                    }
                }
            }
            tarOut.flush();
            tarOut.close();
            logger.info("成功把源文件打为tar包,名称为:[" + dest.getName() + "]");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            try {
                if (tarOut != null) {
                    tarOut.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

 

二、        gzip压缩、解压

注意gzip不支持压缩目录的;Jdk里提供了类支持压缩文件;默认生成.gz文件

主要对应的Java类为:

//Gzip输入流
java.util.zip.GZIPInputStream
//Gzip输出流
java.util.zip.GZIPOutputStream

 

压缩源代码

/**
	 * gzip 压缩,跟源文件在相同目录中生成.gz文件
	 * @param source 源文件
	 */
	public static void gzip(File source){
		logger.info("开始对源文件["+source.getName()+"]压缩成.gz包");
		String dir = source.getParent();
		File target = new File(dir + "\\" +source.getName() + ".gz");
		FileInputStream fis = null;
		FileOutputStream fos = null;
		GZIPOutputStream gzipOS = null;
		try{
			fis = new FileInputStream(source);
			fos = new FileOutputStream(target);
			gzipOS = new GZIPOutputStream(fos);
			int count = -1;
			byte [] buffer = new byte[1024];
			while((count = fis.read(buffer, 0, buffer.length)) != -1){
				gzipOS.write(buffer, 0, count);
			}
			gzipOS.flush();
			gzipOS.close();
			logger.info("成功把源文件["+source.getName()+"]压缩为.gz包["+target.getName()+"]");
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}finally{
			try{
				if(fis!=null){
					fis.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(fos!=null){
					fos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(gzipOS!=null){
					gzipOS.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
		}
	}

 

解压.gz包源代码

/**
	 * 解压.gz包
	 * @param source 源.gz包
	 */
	public static void ungzip(File source){
		GZIPInputStream gzipIS = null;
		FileInputStream fis = null;
		FileOutputStream fos = null;
		BufferedOutputStream bos = null;
		
		String fileName = source.getName();
		fileName = fileName.substring(0, fileName.lastIndexOf("."));
		try{
			fis = new FileInputStream(source);
			gzipIS = new GZIPInputStream(fis);
			File target = new File(source.getParent() + "\\" + fileName);
			fos = new FileOutputStream(target);
			bos = new BufferedOutputStream(fos);
			
			int count = -1;
			byte []buffer = new byte[1024];
			while((count = gzipIS.read(buffer, 0, buffer.length)) != -1){
				bos.write(buffer, 0, count);
			}
			bos.flush();
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}finally{
			try{
				if(fis!=null){
					fis.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(fos!=null){
					fos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(bos != null){
					bos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(gzipIS!=null){
					gzipIS.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
		}
	}

 

 

三、        zip压缩、解压

Jdk提供代码技术支持,tar打包跟zip压缩类似的。

在Jdk中主要的类为:

java.util.zip.ZipOutputStream
java.util.zip.ZipInputStream

 

压缩源代码

/**
	 * 使用zip压缩文件
	 * @param source 源文件或者文件夹
	 */
	public static void zip(File source){
		String dir = source.getParent();
		File target = new File(dir + "\\" +source.getName() + ".zip");
		FileOutputStream fos = null;
		ZipOutputStream zipos = null;
		
		try{
			fos = new FileOutputStream(target);
			zipos = new ZipOutputStream(fos);
			zipFile(source, zipos, "");
			//必须要下面一步,否则会报no such file or directory错误
			zipos.close();
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}finally{
			try {
				if(fos != null){
					fos.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			try {
				if(zipos != null){
					zipos.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	/**
	 * 递归压缩文件或者文件夹
	 * @param source 源文件
	 * @param zipos zip输出流
	 * @param parentPath 路径 
	 */
	public static void zipFile(File source,ZipOutputStream zipos,String parentPath){
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		try {
			//增加目录 
			if(source.isDirectory()){
				File[]files = source.listFiles();
				if(files.length < 1){
					ZipEntry entry = new ZipEntry(parentPath + source.getName()  + "/");
					zipos.putNextEntry(entry);
				}
				for (File file : files) {
					zipFile(file, zipos, parentPath + source.getName() + "/");
				}
			}else if(source.isFile()){
				fis = new FileInputStream(source);
				bis = new BufferedInputStream(fis);
				ZipEntry entry = new ZipEntry(parentPath + source.getName());
				zipos.putNextEntry(entry);
				int count = -1;
				byte []buffer = new byte[1024];
				while((count = bis.read(buffer, 0, buffer.length)) != -1){
					zipos.write(buffer, 0, count);
				}
				fis.close();
				bis.close();
			}
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
		}finally{
			try {
				if(bis != null){
					bis.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			try {
				if(fis != null){
					fis.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

 

解压源代码

/**
	 * 解压zip文件
	 * @param source 源.zip文件
	 */
	public static void unzip(File source){
		ZipInputStream zipIn = null;
		FileInputStream fis = null;
		String parentPath = source.getParent();
		
		System.out.println(parentPath);
		BufferedOutputStream bos = null;
		FileOutputStream fos = null;
		try{
			fis = new FileInputStream(source);
			zipIn = new ZipInputStream(fis);
			ZipEntry entry = null;
			while((entry = zipIn.getNextEntry()) != null){
				File file = new File(parentPath + "\\" + entry.getName());
				
				//为了空目录的出现
				if(entry.isDirectory()){
					file.mkdirs();
					continue;
				}
				
				File parentDir = file.getParentFile();
				if(!parentDir.exists()){
					parentDir.mkdirs();
				}
				fos = new FileOutputStream(file);
				bos = new BufferedOutputStream(fos);
				int count = -1;
				byte []buffer = new byte[1024];
				while((count = zipIn.read(buffer, 0, buffer.length)) != -1){
					bos.write(buffer, 0, count);
				}
				bos.flush();
				bos.close();
				fos.close();
			}
			zipIn.close();
		}catch (Exception e) {
			logger.error(e.getMessage(),e);
		}finally{
			try{
				if(fis != null){
					fis.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(fos != null){
					fos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(bos != null){
					bos.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
			try{
				if(zipIn != null){
					zipIn.close();
				}
			}catch (Exception e) {
				logger.error(e.getMessage(),e);
			}
		}
	}

 

 

 

 

    原文作者:递归算法
    原文地址: https://blog.csdn.net/psyuhen/article/details/9470005
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞