java实现文件夹压缩

java实现包含文件的文件夹ZIP压缩,总结如下:

  • 解决中文乱码的问题,ZipOutputStream用org.apache.tools.zip.(而不是用java.util.zip.),指定编码为GBK;
  • ZipEntry的setTime(long long)方法可以设置压缩文件或压缩文件夹的最后修改时间;
  • 先调用outputStream的flush()再关闭流,流如果未正常关闭,则会在解压的时候出现压缩文件损坏的现象;
  • 示例中包含压缩完成后递归删除源文件;
  • 路径下如果有同名文件存在又不愿意覆盖处理,给了一个依次添加后缀(1)、(2)……的小方法;
  • 创建文件和文件夹时有些非法字符不支持(示例方法中,非法字符的字符串包含了很多字符,可以按需增减)。因为某些符号在正则表达示中有相应意义,所以要加上“\\”表示转义,否则在使用replaceAll()时会报错,例如java.util.regex.PatternSyntaxException: Dangling meta character ‘*’ near index 0
package com.mytest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.springframework.util.StringUtils;
/**
 * 
 * 文件压缩成zip
 *
 */
public class ZipCompressService {

	/**
	 * 
	 * 将文件夹及文件夹包含的内容压缩成zip文件
	 * (为了解决中文乱码的问题,ZipOutputStream用org.apache.tools.zip.*)
	 * 
	 * @param inputFile 源文件
	 * @param delFlag 删除源文件标记
	 * @return File 压缩后的文件
	 */
	public File zipCompress(File inputFile, boolean delFlag) throws Exception{
		File zipFile = null;
		//创建zip输出流
		//为了解决中文乱码的问题,ZipOutputStream用org.apache.tools.zip.*
		//不要用 java.util.zip.*
		ZipOutputStream zos = null;
		if(inputFile != null && inputFile.exists()) {
			try {
				String path = inputFile.getCanonicalPath();
				String zipFileName = path + ".zip";
				zipFile = new File(zipFileName);
				if(zipFile.exists()) {
					zipFile.delete();
				}
				zipFile.createNewFile();//创建文件
				zos = new ZipOutputStream(new FileOutputStream(zipFile));
				//解决中文乱码问题,指定编码GBK
				zos.setEncoding("GBK");
				//压缩文件或文件夹 
				this.compressFile(zos, inputFile, inputFile.getName());
			}catch(Exception e) {
				System.out.println("文件压缩异常:" + e);
				throw e;
			}finally {
				try {
					if(zos != null) {
						//先调用outputStream的flush()再关闭流;
						//流如果未正常关闭,则会在解压的时候出现压缩文件损坏的现象
						zos.flush();
						zos.close();
					}
					
					if(delFlag) {
						//递归删除源文件及源文件夹
						this.deleteFile(inputFile);
					}
				}catch(Exception ex) {
					System.out.println("输出流关闭异常:" + ex);
				}
			}
		}
		return zipFile;
	}
	
	/**
	 * 压缩文件或文件夹
	 * (ZipEntry 使用org.apache.tools.zip.*,不要用 java.util.zip.*)
	 * 
	 * @param zos zip输出流
	 * @param sourceFile 源文件
	 * @param baseName 父路径
	 * @throws Exception 异常
	 */
	private void compressFile(ZipOutputStream zos, File sourceFile, String baseName) throws Exception{
		if(!sourceFile.exists()) {
			return;
		}
		
		//若路径为目录(文件夹)
		if(sourceFile.isDirectory()) {
			//取出文件夹中的文件(或子文件夹)
			File[] fileList = sourceFile.listFiles();
			//若文件夹为空,则创建一个目录进入点
			if(fileList.length == 0) {
				//文件名称后跟File.separator表示这是一个文件夹
				zos.putNextEntry(new ZipEntry(baseName + File.separator));
			//若文件夹非空,则递归调用compressFile,对文件夹中的每个文件或每个文件夹进行压缩
			}else {
				for(int i = 0; i < fileList.length; i++) {
					this.compressFile(zos, fileList[i], 
							baseName + File.separator + fileList[i].getName());
				}
			}
			
		//若为文件,则先创建目录进入点,再将文件写入zip文件中	
		}else {
			ZipEntry ze = new ZipEntry(baseName);
			//设置ZipEntry的最后修改时间为源文件的最后修改时间
			ze.setTime(sourceFile.lastModified());
			zos.putNextEntry(ze);
			
			FileInputStream fis = new FileInputStream(sourceFile);
			this.copyStream(fis, zos);
			try {
				if(fis != null) {
					fis.close();
				}
			}catch(Exception e) {
				System.out.println("输入流关闭异常:" + e);
			}
		}
	}
	
	/**
	 * 流拷贝
	 * 
	 * @param in 输入流
	 * @param out 输出流
	 * @throws IOException
	 */
	private void copyStream(InputStream in, OutputStream out) throws IOException{
		int bufferLength = 1024 * 100;
		synchronized(in) {
			synchronized(out) {
				int count = 0;
				byte[] buffer = new byte[bufferLength];
				while((count = in.read(buffer, 0, bufferLength)) != -1) {
					out.write(buffer, 0, count);
				}
				out.flush();
			}
		}
	}
	
	/**
	 * 递归删除文件夹中的目录及文件
	 * 
	 * @param sourceFile
	 * @throws Exception
	 */
	private void deleteFile(File sourceFile) throws Exception{
		//如果路径为目录
		if(sourceFile.isDirectory()) {
			//取出文件夹中的文件或子文件夹
			File[] fList = sourceFile.listFiles();
			if(fList.length == 0) {
				sourceFile.delete();
			}else {
				for(int i = 0; i < fList.length; i++) {
					this.deleteFile(fList[i]);
				}
				sourceFile.delete();
			}
		//如果为文件则直接删除
		}else {
			sourceFile.delete();
		}
	}
	
	/**
	 *     当前路径下若已有同名文件又不愿意覆盖,
	 *     则依次追加后缀
	 * 
	 * @param path
	 * @param docName
	 * @return
	 * @throws Exception
	 */
	private File createFile(String path, final String docName) throws Exception{
		//创建目标文件
		File destFile = new File(path, docName);
		//如果路径下存在同名文件又不愿意覆盖,
		//那么则依次给文件加后缀(2)、(3)……
		if(destFile.exists()) {
			int i = 1;
			do {
				++i;
				//按“.”分割
				String[] doc = docName.split("\\.");
				destFile = new File(path, doc[0] + "(" + i + ")" + "." + doc[1]);
				
				//直到文件创建成功则跳出循环
			}while(!destFile.createNewFile());
		}else {
			destFile.createNewFile();
		}
		return destFile;
	}
	
	/**
	 * 过滤非法字符
	 * @param inputStr 输入字符串
	 * @return
	 */
	private String filterIllegalSymbol(String inputStr) {
		if(StringUtils.isEmpty(inputStr)) {
			return null;
		}
		String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?]|\n|\r|\t";
		Pattern pattern = Pattern.compile(regEx);
		Matcher matcher = pattern.matcher(inputStr);
		//若包含非法字符则循环处理
		if(matcher.find()) {
			char[] regExCharArray = regEx.toCharArray();
			for(int i = 0; i < regExCharArray.length; i++) {
				char c = regExCharArray[i];
				System.out.println(i + " 当前字符:" + c);
				if(inputStr.indexOf(c) != -1) {
					System.out.println("过滤前:" + inputStr);
					//因为某些符号在正则表达示中有相应意义,所以要加上“\\”表示转义,
					//否则会报错,例如java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 0
					inputStr = inputStr.replaceAll("\\" + String.valueOf(c), "");
					System.out.println("过滤后:" +inputStr);
				}
			}
		}
		//测试用
		System.out.println(inputStr);
		return inputStr;
		
	}
	
	public static void main(String[] args) {
		ZipCompressService service = new ZipCompressService();
		service.filterIllegalSymbol("这是一个*包含非/法字:符$%<的字符串>|");
	}
}





  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值