一、背景
前端时间,自己做的项目需要打包功能,不想再引外部的jar包
便用java.util.zip做了下该功能
二、适用场景
生成多个word、excel、xml等文件,并要求打包下载的情形
例:项目信息的多选导出word
三、实现
实现分为三个部分,分别是
1、将字符串保存为文件,都是最基本的IO操作
/*** @Description 将字符串保存为文件
*@authorliuy-8
* @date 2015年5月20日 下午1:48:18
*@paramfilePath
*@paramcontent*/
public static voidsaveFile(String filePath, String content){
File file= newFile(filePath);
FileWriter fw= null;//这里没有使用BufferWrite,是因为数据是一次性写入//BufferWrite的优势在于调用write方法时,使用缓冲区//而FileWriter每次调用write方法,都调用StreamEncoder的write方法
try{
fw= new FileWriter(file);//缓冲区1024字符
fw.write(content);
fw.flush();
}catch(IOException e) {
e.printStackTrace();
}finally{//关闭FileWriter
try{if(null !=fw)
fw.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
2、扫描指定文件夹下所有的文件,准备压缩包的写入工作
这一部分依然是基本的IO操作,要注意安全关闭输入输出流,打开与关闭的顺序
/*** @Description 获取文件夹中所有文件路径
*@authorliuy-8
* @date 2015年5月27日 下午5:25:24
*@paramfolderPath 文件夹路径
*@return文件夹中所有文件路径*/
public static ListgetFilesPath(String folderPath){
List filesPath = new ArrayList();
File folder= newFile(folderPath);
File[] fileList=folder.listFiles();for(File file : fileList){if(file.isDirectory()){//是文件夹,递归遍历
filesPath.addAll(getFilesPath(file.getPath()));
}else{//是文件,加入文件列表
filesPath.add(file.getPath());
}
}returnfilesPath;
}/*** @Description 压缩文件夹
*@authorliuy-8
* @date 2015年5月26日 下午1:42:00
*@paramfolderPath 文件夹路径
*@paramzipFilePath 压缩文件路径*/
public static voidfolder2Zip(String folderPath, String zipFilePath){//获取当前系统文件分隔符
String fileSeparator = System.getProperty("file.separator");//若传入路径最后没有文件分隔符,加上
if(folderPath.lastIndexOf(fileSeparator) != (folderPath.length() - 1)){
folderPath= folderPath +fileSeparator;
}//获取文件夹下所有文件路径
List filesPath =getFilesPath(folderPath);//文件输出流
FileOutputStream fos = null;//缓冲输出流
BufferedOutputStream bos = null;//zip输出流
ZipOutputStream zos = null;try{
fos= newFileOutputStream(zipFilePath);
bos= newBufferedOutputStream(fos);
zos= newZipOutputStream(bos);for(String filePath : filesPath){//将文件写入zip输出流
writeFile2Zip(folderPath, filePath, zos);
}
zos.flush();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally{//关闭zip输出流
try{if(null !=zos){
zos.close();
}
}catch(IOException e) {
e.printStackTrace();
}//关闭缓冲输出流
try{if(null !=bos){
bos.close();
}
}catch(IOException e) {
e.printStackTrace();
}//关闭文件输出流
try{if(null !=fos){
fos.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
3、将文件依次写入zip输出流
在第二步已经用ZipOutputStream创建了压缩文件的输出流,这一步里,每个文件都要对应一个ZipEntry对象
要将这个对象加入到压缩文件的输出流中后再写入数据,并且写完数据必须在输出流中关闭该ZipEntry对象
这里有2个容易出错的地方:
一是ZipEntry对象需要一个路径,这个路径是相对于压缩文件夹的相对路径,用来保证子文件夹文件的顺利压入
二是往zip输出流中写入的字节的时候,要判断循环读取字节时文件输入流中读取了多少字节长度,读多少写多少,不然在文件尾部会出现错误数据
/*** @Description 将文件写入zip输出流
*@authorliuy-8
* @date 2015年5月27日 下午5:23:42
*@paramfolderPath 待压缩文件夹路径
*@paramfilePath 待写入文件
*@paramzos zip输出流*/
private static voidwriteFile2Zip(String folderPath, String filePath, ZipOutputStream zos){//缓冲区
byte[] bs = new byte[1024];//获取文件的相对路径
String entryName = filePath.substring(filePath.indexOf(folderPath) +folderPath.length());//创建zip实体
ZipEntry entry = newZipEntry(entryName);//输入流
FileInputStream fis = null;//缓冲输入流
BufferedInputStream bis = null;try{//将zip实体加入zip输出流
zos.putNextEntry(entry);
fis= newFileInputStream(filePath);
bis= newBufferedInputStream(fis);//写入zip输出流
int len = 0;while((len = bis.read(bs, 0, 1024)) > 0){
zos.write(bs,0, len);
}
zos.flush();
}catch(IOException e) {
e.printStackTrace();
}finally{//关闭entity
try{
zos.closeEntry();
}catch(IOException e) {
e.printStackTrace();
}//关闭BufferedInputStream
try{if(null !=bis){
bis.close();
}
}catch(IOException e) {
e.printStackTrace();
}//关闭FileInputStream
try{if(null !=fis){
bis.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
此类已封装为GlodonFileUtil,有需要找我要即可
原文:http://www.cnblogs.com/xjyh/p/4549520.html