Java文件压缩与解压

JAVA压缩与解压

需要的jar包

<dependency>
	<groupId>com.github.axet</groupId>
	<artifactId>java-unrar</artifactId>
	<version>1.7.0-3</version>
</dependency>
package com.util.base;

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 java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import de.innosystec.unrar.Archive;
import de.innosystec.unrar.NativeStorage;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.rarfile.FileHeader;

/**
 * 打包与解压操作类
 * @author zhanglang
 * 2018-09-26
 */
public class ZipUtil {
	/**  
     * 递归压缩文件夹  
     * @param srcRootDir 压缩文件夹根目录的子路径  
     * @param file 当前递归压缩的文件或目录对象  
     * @param zos 压缩文件存储对象  
     * @throws Exception  
     */    
    private static void zip(String srcRootDir, File file, ZipOutputStream zos) throws Exception {    
        if (file == null){    
            return;    
        }                   
        //如果是文件,则直接压缩该文件    
        if (file.isFile()){               
            int count, bufferLen = 2048;    
            byte data[] = new byte[bufferLen];    
                
            //获取文件相对于压缩文件夹根目录的子路径    
            String subPath = file.getAbsolutePath();    
            int index = subPath.indexOf(srcRootDir);    
            if (index != -1){    
                subPath = subPath.substring(srcRootDir.length() + File.separator.length());    
            }    
            ZipEntry entry = new ZipEntry(subPath);    
            zos.putNextEntry(entry);    
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));    
            while ((count = bis.read(data, 0, bufferLen)) != -1){    
                zos.write(data, 0, count);    
            }    
            bis.close();    
            zos.closeEntry();    
        } else { 
        	//如果是目录,则压缩整个目录    
            //压缩目录中的文件或子目录    
            File[] childFileList = file.listFiles();    
            if(childFileList != null) {
            	for (int n=0; n<childFileList.length; n++){    
                    childFileList[n].getAbsolutePath().indexOf(file.getAbsolutePath());    
                    zip(srcRootDir, childFileList[n], zos);    
                } 
            }
        }    
    }    
    
    /**  
     * 对文件或文件目录进行压缩  
     * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径  
     * @param zipPath 压缩文件保存的路径。注意:zipPath不能是srcPath路径下的子文件夹  
     * @param zipFileName 压缩文件名  
     * @throws Exception  
     */    
    public static void zip(String srcPath, String zipPath, String zipFileName) throws Exception {    
        if (StringUtils.isEmpty(srcPath) 
        		|| StringUtils.isEmpty(zipPath) 
        		|| StringUtils.isEmpty(zipFileName)){    
            throw new TzException("Parameter null error.");    
        }    
        CheckedOutputStream cos = null;    
        ZipOutputStream zos = null;                         
        try{    
            File srcFile = new File(srcPath);    
                
            //判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)    
            if (srcFile.isDirectory() && zipPath.indexOf(srcPath)!=-1){    
                throw new TzException("zipPath must not be the child directory of srcPath.");    
            }    
                
            //判断压缩文件保存的路径是否存在,如果不存在,则创建目录    
            File zipDir = new File(zipPath);    
            if (!zipDir.exists() || !zipDir.isDirectory()){    
                zipDir.mkdirs();    
            }    
                
            //创建压缩文件保存的文件对象    
            String zipFilePath = zipPath + (zipPath.endsWith(File.separator) ? "" : File.separator) + zipFileName;    
            File zipFile = new File(zipFilePath);               
            if (zipFile.exists()){    
                //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException
//                SecurityManager securityManager = new SecurityManager();    
//                securityManager.checkDelete(zipFilePath);
                //删除已存在的目标文件
                zipFile.delete();                   
            }    
                
            cos = new CheckedOutputStream(new FileOutputStream(zipFile), new CRC32());    
            zos = new ZipOutputStream(cos);    
                
            //如果只是压缩一个文件,则需要截取该文件的父目录    
            String srcRootDir = srcPath;    
            if (srcFile.isFile()){    
                int index = srcPath.lastIndexOf(File.separator);    
                if (index != -1){    
                    srcRootDir = srcPath.substring(0, index);    
                }    
            }    
            //调用递归压缩方法进行目录或文件压缩    
            zip(srcRootDir, srcFile, zos);    
            zos.flush();    
        } catch (Exception e){    
            throw e;    
        } finally {               
            try{    
                if (zos != null){    
                    zos.close();    
                }                   
            }catch (Exception e){    
                e.printStackTrace();    
            }               
        }    
    }    

    /**  
     * 解压缩zip包  
     * @param zipFilePath zip文件的全路径  
     * @param unzipFilePath 解压后的文件保存的路径  
     */
    @SuppressWarnings("unchecked")
	public static void unZip(String zipFilePath, String unzipFilePath) 
    		throws TzException {
    	if (StringUtils.isEmpty(zipFilePath) 
        		|| StringUtils.isEmpty(unzipFilePath)){    
            throw new TzException("参数错误");              
        }
        
        File zipFile = new File(zipFilePath);    
        if (!zipFile.exists()) {
            throw new TzException(zipFile.getPath() + "所指文件不存在");
        }
        
        //创建解压缩文件保存的路径    
        File unzipFileDir = new File(unzipFilePath);    
        if (!unzipFileDir.exists() || !unzipFileDir.isDirectory()){    
            unzipFileDir.mkdirs();    
        }    
        
        if (zipFilePath.toLowerCase().endsWith(".rar")) {
        	unRar(zipFilePath, unzipFilePath);
    	}else {
    		if (!zipFilePath.toLowerCase().endsWith(".zip")) {
	            throw new TzException("文件不是zip压缩文件");
	        }
	        //开始解压
	        int count = 0, bufferSize = 2048;    
	        byte[] buffer = new byte[bufferSize];
	        ZipFile zip = null;
	        try {
		        zip = new ZipFile(zipFile, Charset.forName("GBK"));
		        Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>)zip.entries();    
		        //循环对压缩包里的每一个文件进行解压         
		        while(entries.hasMoreElements()){    
		        	ZipEntry entry = entries.nextElement();
		        	
		        	if (entry.isDirectory()) {
		                String dirPath = unzipFilePath + File.separator + entry.getName();
		                File dir = new File(dirPath);
		                //如果文件夹路径不存在,则创建文件夹    
		                if (!dir.exists()){    
		                	dir.mkdirs();
		                }
		            } else {
		            	//构建压缩包中一个文件解压后保存的文件全路径    
		                String entryFilePath = unzipFilePath + File.separator + entry.getName();    
		                
		                //创建解压文件    
		                File entryFile = new File(entryFilePath);    
		                if (entryFile.exists()){    
		                    //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException    
		                    //SecurityManager securityManager = new SecurityManager();    
		                    //securityManager.checkDelete(entryFilePath);
		                    //删除已存在的目标文件    
		                    entryFile.delete();
		                }    
		                    
		                //写入文件    
		                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(entryFile));  
		                BufferedInputStream bis = new BufferedInputStream(zip.getInputStream(entry));    
		                while ((count = bis.read(buffer, 0, bufferSize)) != -1){    
		                    bos.write(buffer, 0, count);    
		                }  
		                //关闭
		                if(null != bis) bis.close();
		                if(null != bos){
		                	 bos.flush();    
		                     bos.close();
		                }
		            }
		        }
	        } catch (Exception e) {
	        	e.printStackTrace();
	            throw new TzException("解压失败", e);
	        } finally {
	            if(zip != null){
	                try {
	                	zip.close();
	                } catch (IOException e) {
	                    e.printStackTrace();
	                }
	            }
	        }
    	}
    }
    
    /**
     * 根据原始rar路径,解压到指定文件夹下. winrar5.0以上版本压缩文件解压异常
     * @param srcRarPath 原始rar路径
     * @param dstDirectoryPath 解压到的文件夹
     * @throws TzException 
     */
    public static void unRar(String srcRarPath, String dstDirectoryPath) 
    		throws TzException {
    	if (StringUtils.isEmpty(srcRarPath) 
        		|| StringUtils.isEmpty(dstDirectoryPath)){    
            throw new TzException("参数错误");              
        }
    	
    	File zipFile = new File(srcRarPath);
        if (!zipFile.exists()) {
        	throw new TzException(zipFile.getPath() + "所指文件不存在");
        }
    	
    	if (srcRarPath.toLowerCase().endsWith(".zip")) {
    		unZip(srcRarPath, dstDirectoryPath);
    	}else {
	        if (!srcRarPath.toLowerCase().endsWith(".rar")) {
	            throw new TzException("文件不是rar压缩文件");
	        }
	        File dstDiretory = new File(dstDirectoryPath);
	        if (!dstDiretory.exists()) {// 目标目录不存在时,创建该文件夹
	            dstDiretory.mkdirs();
	        }
	        Archive a = null;
	        FileOutputStream os = null;
	        try {
	        	NativeStorage nsFile = new NativeStorage(new File(srcRarPath));
	            a = new Archive(nsFile);
	            if (a != null) {
	                a.getMainHeader().print(); // 打印文件信息.
	                FileHeader fh = a.nextFileHeader();
	                while (fh != null) {
	                    String fileName=  fh.getFileNameW().trim();
	                    if(!existZH(fileName)){
	                        fileName = fh.getFileNameString().trim();
	                    }
	                    if (fh.isDirectory()) { // 文件夹
	                        File fol = new File(dstDirectoryPath + File.separator + fileName);
	                        fol.mkdirs();
	                    } else { // 文件
	                        File out = new File(dstDirectoryPath + File.separator + fileName.trim());
	                        
	                        try {// 之所以这么写try,是因为万一这里面有了异常,不影响继续解压.
	                            if (!out.exists()) {
	                                if (!out.getParentFile().exists()) {// 相对路径可能多级,可能需要创建父目录.
	                                    out.getParentFile().mkdirs();
	                                }
	                                out.createNewFile();
	                            }
	                            os = new FileOutputStream(out);
	                            a.extractFile(fh, os);
	                            os.close();
	                            os = null;
	                        } catch (Exception ex) {
	                            ex.printStackTrace();
	                        }
	                    }
	                    fh = a.nextFileHeader();
	                }
	                a.close();
	                a = null;
	            }
	        }catch(RarException e) {
	        	e.printStackTrace();
	        	throw new TzException("程序不支持该压缩格式,请将文件压缩成rar4或zip格式", e);
	        }catch(Exception e){    
	        	e.printStackTrace();
	        	throw new TzException("解压失败", e);   
	        }finally{
	            if(os!=null){    
	                try{
	                	os.close();
	                	os=null;
	                }catch(Exception e){
	                	e.printStackTrace();
	                }    
	            }    
	            if(a!=null){   
	                try{
	                	a.close();
	                	a=null;
	                }catch(Exception e){
	                	e.printStackTrace();
	                }    
	            }    
	        }  
    	}
    }
    
    /**
     * 删除单个文件
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                System.out.println("删除单个文件" + fileName + "成功!");
                return true;
            } else {
                System.out.println("删除单个文件" + fileName + "失败!");
                return false;
            }
        } else {
            System.out.println("删除单个文件失败:" + fileName + "不存在!");
            return false;
        }
    }

    
    /**
     * 删除目录及目录下的文件
     * @param dir 要删除的目录的文件路径
     * @return 目录删除成功返回true,否则返回false
     */
    public static boolean deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾,自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        // 如果dir对应的文件不存在,或者不是一个目录,则退出
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            System.out.println("删除目录失败:" + dir + "不存在!");
            return false;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                flag = ZipUtil.deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                flag = ZipUtil.deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) {
            System.out.println("删除目录失败!");
            return false;
        }
        // 删除当前目录
        if (dirFile.delete()) {
            System.out.println("删除目录" + dir + "成功!");
            return true;
        } else {
            return false;
        }
    }

    //判断是否包含中文
    private static boolean existZH(String str) {
        String regEx = "[\\u4e00-\\u9fa5]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        while (m.find()) {
            return true;
        }
        return false;
    }
    
    //生成随机文件名,与文件上传命名一致
    public static String getNowTime() {
		Calendar cal = Calendar.getInstance();
		int year = cal.get(1);
		int month = cal.get(2) + 1;
		int day = cal.get(5);
		int hour = cal.get(10);
		int minute = cal.get(12);
		int second = cal.get(13);
		int mi = cal.get(14);
		long num = cal.getTimeInMillis();
		int rand = (int) (Math.random() * 899999 + 100000);
		return (new StringBuilder()).append(year).append(month).append(day).append(hour).append(minute).append(second)
				.append(mi).append(num).append("_").append(rand).toString();
	}

    
    /* sFile:原文件地址,tFile目标文件地址 */
	public static void copyFile(String sFile, String tFile) {
		// System.out.println("原文件地址"+sFile+"目标"+tFile);
		FileInputStream fi = null;
		FileOutputStream fo = null;
		FileChannel in = null;
		FileChannel out = null;

		File s = new File(sFile);
		File t = new File(tFile);
		if (s.exists() && s.isFile()) {
			// System.out.println("是文件");
			try {
				fi = new FileInputStream(s);
				fo = new FileOutputStream(t);
				in = fi.getChannel();// 得到对应的文件通道
				out = fo.getChannel();// 得到对应的文件通道
				in.transferTo(0, in.size(), out);// 连接两个通道,并且从in通道读取,然后写入out通道
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					fi.close();
					in.close();
					fo.close();
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void copyFile2(String sFile, String tFile) {
		File srcFile = new File(sFile);
		if(srcFile.exists()){
			File destFile = new File(tFile);
			try {
				FileUtils.copyFile(srcFile, destFile);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

posted @ 2021-12-09 18:39  CheungLang  阅读(456)  评论(0)    收藏  举报