java
由于业务需求,最近需要用到压缩文件的解压和压缩文件功能,在网上找到很多很好的例子,参考前辈的成果,加了点自己的需求,实现zip文件的递归解压
importjava.io.BufferedOutputStream;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.zip.CRC32;
importjava.util.zip.CheckedOutputStream;
importorg.apache.commons.lang.StringUtils;
importorg.apache.log4j.Logger;
importorg.apache.tools.zip.ZipEntry;
importorg.apache.tools.zip.ZipOutputStream;
/**
*功能:使用ApacheAnt里提供的org.apache.tools.zip实现zip压缩和解压(支持中文文件名)
*解决了由于java.util.zip包不支持汉字的问题。使用java.util.zip包时,当zip文件中有名字为中文的文件时,
*就会出现异常:"Exceptioninthread"main"java.lang.IllegalArgumentExceptionat
*java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:285)
*
*/
publicclassAntZipUtil{
privatestaticListlist=newArrayList();
privatestaticLoggerlog=Logger.getLogger(AntZipUtil.class);
privatestaticListlistFile(Stringpath){
Filefile=newFile(path);
String[]array=null;
StringsTemp="";
if(!file.isDirectory()){
returnnull;
}
array=file.list();
if(array.length>0){
for(inti=0;i<array.length;i++){
sTemp=path+array[i];
file=newFile(sTemp);
if(file.isDirectory()){
listFile(sTemp+"/");
}else
list.add(sTemp);
}
}else{
returnnull;
}
returnlist;
}
publicstaticvoidzip(Stringneedtozipfilepath,Stringzipfilepath){
try{
byte[]b=newbyte[512];
Fileneedtozipfile=newFile(needtozipfilepath);
if(!needtozipfile.exists()){
System.err.println("指定的要压缩的文件或目录不存在.");
return;
}
StringzipFile=zipfilepath;
FiletargetFile=newFile(zipFile.substring(0,
zipFile.indexOf("\\")+1));
if(!targetFile.exists()){
System.out.println("指定的目标文件或目录不存在.");
return;
}
Stringfilepath=needtozipfilepath;
ListfileList=listFile(filepath);
FileOutputStreamfileOutputStream=newFileOutputStream(zipFile);
CheckedOutputStreamcs=newCheckedOutputStream(fileOutputStream,
newCRC32());
ZipOutputStreamout=newZipOutputStream(newBufferedOutputStream(
cs));
for(inti=0;i<fileList.size();i++){
InputStreamin=newFileInputStream((String)fileList.get(i));
StringfileName=((String)fileList.get(i)).replace(
File.separatorChar,'/');
fileName=fileName.substring(fileName.indexOf("/")+1);
ZipEntrye=newZipEntry(fileName);
out.putNextEntry(e);
intlen=0;
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
out.closeEntry();
}
out.close();
}catch(Exceptione){
log.error("",e);
}
}
/**
*压缩文件或者文件夹
*
*@parambaseDirName
*压缩的根目录
*@paramfileName
*根目录下待压缩的文件或文件夹名
*@paramtargetFileName
*目标ZIP文件星号"*"表示压缩根目录下的全部文件
*
*/
publicstaticbooleanzip(StringbaseDirName,ListfileNames,
StringtargetFileName,Stringencoding){
booleanflag=false;
try{
//判断"压缩的根目录"是否存在!是否是一个文件夹!
FilebaseDir=newFile(baseDirName);
if(!baseDir.exists()||(!baseDir.isDirectory())){
System.err.println("压缩失败!根目录不存在:"+baseDirName);
returnfalse;
}
//得到这个"压缩的根目录"的绝对路径
StringbaseDirPath=baseDir.getAbsolutePath();
//由这个"目标ZIP文件"文件名得到一个压缩对象ZipOutputStream
FiletargetFile=newFile(targetFileName);
ZipOutputStreamout=newZipOutputStream(newFileOutputStream(
targetFile));
//中文有乱码,引进下面的改造类
//CnZipOutputStreamout=newCnZipOutputStream(new
//FileOutputStream(targetFile),encoding);
//设置压缩编码ApacheAnt有个包专门处理ZIP文件,可以指定文件名的编码方式。由此可以解决问题。例如:用
//org.apache.tools.zip.ZipOutputStream代替java.util.zip.ZipOutputStream。ZipOutputStream
//out=.....;out.setEncoding("GBK");
//out.setEncoding("GBK");//设置为GBK后在windows下就不会乱码了,如果要放到Linux或者Unix下就不要设置了
out.setEncoding(encoding);
//"*"表示压缩包括根目录baseDirName在内的全部文件到targetFileName文件下
if(fileNames.equals("*")){
AntZipUtil.dirToZip(baseDirPath,baseDir,out);
}else{
File[]files=newFile[fileNames.size()];
for(inti=0;i<fileNames.size();i++){
//根据parent抽象路径名和child路径名字符串创建一个新File实例。
files[i]=newFile(baseDir,(String)fileNames.get(i));
}
if(files[0].isFile()){
//调用本类的一个静态方法压缩一个文件
//CompressUtil.fileToZip(baseDirPath,file,out);
AntZipUtil.filesToZip(baseDirPath,files,out);
}
}
out.close();
flag=true;
}catch(FileNotFoundExceptione){
log.error("",e);
}catch(IOExceptione){
log.error("",e);
}
returnflag;
}
/**
*将文件压缩到Zip输出流
*
*@parambaseDirPath
*根目录路径
*@paramfile
*要压缩的文件
*@paramout
*输出流
*@throwsIOException
*/
privatestaticvoidfileToZip(StringbaseDirPath,Filefile,
ZipOutputStreamout)throwsIOException{
FileInputStreamin=null;
org.apache.tools.zip.ZipEntryentry=null;
//创建复制缓冲区1024*4=4K
byte[]buffer=newbyte[1024*4];
intbytes_read=0;
if(file.isFile()){
in=newFileInputStream(file);
//根据parent路径名字符串和child路径名字符串创建一个新File实例
StringzipFileName=getEntryName(baseDirPath,file);
entry=neworg.apache.tools.zip.ZipEntry(zipFileName);
//"压缩文件"对象加入"要压缩的文件"对象
out.putNextEntry(entry);
//现在是把"要压缩的文件"对象中的内容写入到"压缩文件"对象
while((bytes_read=in.read(buffer))!=-1){
out.write(buffer,0,bytes_read);
}
out.closeEntry();
in.close();
}
}
/**
*多个文件目录压缩到Zip输出流
*
*@parambaseDirPath
*@paramfiles
*@paramout
*@throwsIOException
*/
@SuppressWarnings("unused")
privatestaticvoidfilesToZip(StringbaseDirPath,File[]files,
ZipOutputStreamout)throwsIOException{
//遍历所有的文件一个一个地压缩
for(inti=0;i<files.length;i++){
Filefile=files[i];
if(file.isFile()){
//调用本类的一个静态方法压缩一个文件
AntZipUtil.fileToZip(baseDirPath,file,out);
}else{
/*
*这是一个文件夹所以要再次得到它下面的所有的文件这里是自己调用自己..............递归..........
*/
AntZipUtil.dirToZip(baseDirPath,file,out);
}
}
}
/**
*将文件目录压缩到Zip输出流
*
*@parambaseDirPath
*@paramdir
*@paramout
*@throwsIOException
*/
privatestaticvoiddirToZip(StringbaseDirPath,Filedir,
ZipOutputStreamout)throwsIOException{
//得到一个文件列表(本目录下的所有文件对象集合)
File[]files=dir.listFiles();
//要是这个文件集合数组的长度为0,也就证明了这是一个空的文件夹,虽然没有再循环遍历它的必要,但是也要把这个空文件夹也压缩到目标文件中去
if(files.length==0){
//根据parent路径名字符串和child路径名字符串创建一个新File实例
StringzipFileName=getEntryName(baseDirPath,dir);
org.apache.tools.zip.ZipEntryentry=neworg.apache.tools.zip.ZipEntry(
zipFileName);
out.putNextEntry(entry);
out.closeEntry();
}else{
//遍历所有的文件一个一个地压缩
for(inti=0;i<files.length;i++){
Filefile=files[i];
if(file.isFile()){
//调用本类的一个静态方法压缩一个文件
AntZipUtil.fileToZip(baseDirPath,file,out);
}else{
/*
*这是一个文件夹所以要再次得到它下面的所有的文件
*这里是自己调用自己..............递归..........
*/
AntZipUtil.dirToZip(baseDirPath,file,out);
}
}
}
}
/**
*获取待压缩文件在ZIP文件中的entry的名字,即相对于根目录的相对路径名
*
*@parambaseDirPath
*根目录
*@paramfile
*@return
*/
privatestaticStringgetEntryName(StringbaseDirPath,Filefile){
/**
*改变baseDirPath的形式把"C:/temp"变成"C:/temp/"
*/
if(!baseDirPath.endsWith(File.separator)){
baseDirPath+=File.separator;
}
StringfilePath=file.getAbsolutePath();
/**
*测试此抽象路径名表示的文件是否是一个目录。要是这个文件对象是一个目录则也要变成后面带"/"这个文件对象类似于
*"C:/temp/人体写真/1.jpg"要是这个文件是一个文件夹则也要变成后面带"/"
*因为你要是不这样做,它也会被压缩到目标文件中但是却不能正解显示也就是说操作系统不能正确识别它的文件类型(是文件还是文件夹)
*/
if(file.isDirectory()){
filePath+="/";
}
intindex=filePath.indexOf(baseDirPath);
returnfilePath.substring(index+baseDirPath.length());
}
////////////////////////////解压缩////////////////////////////////////////
/**
*调用org.apache.tools.zip实现解压缩,支持目录嵌套和中文名
*也可以使用java.util.zip不过如果是中文的话,解压缩的时候文件名字会是乱码
*。原因是解压缩软件的编码格式跟java.util.zip.ZipInputStream的编码字符集(固定是UTF-8)不同
*
*@paramzipFileName
*要解压缩的文件
*@paramoutputDirectory
*要解压到的目录
*@throwsException
*/
publicstaticbooleanunZip(StringzipFileName,StringoutputDirectory){
booleanflag=false;
try{
org.apache.tools.zip.ZipFilezipFile=neworg.apache.tools.zip.ZipFile(
zipFileName,"GBK");
java.util.Enumeratione=zipFile.getEntries();
org.apache.tools.zip.ZipEntryzipEntry=null;
createDirectory(outputDirectory,"");
while(e.hasMoreElements()){
zipEntry=(org.apache.tools.zip.ZipEntry)e.nextElement();
if(zipEntry.isDirectory()){
Stringname=zipEntry.getName().toLowerCase();
name=name.substring(0,name.length()-1);
Filef=newFile(outputDirectory+File.separator+name);
f.mkdir();
ListfileList=FileUtil.refreshFileList(outputDirectory
+File.separator+name);
for(inti=0;i<fileList.size();i++){
StringffSt=(String)fileList.get(i);
unZip(ffSt,outputDirectory);
}
log.info("创建目录:"+outputDirectory+File.separator+name);
}else{
StringfileName=zipEntry.getName();
fileName=fileName.replace('\\','/');
if(fileName.indexOf("/")!=-1){
createDirectory(outputDirectory,fileName.substring(0,
fileName.lastIndexOf("/")));
fileName=fileName.substring(
fileName.lastIndexOf("/")+1,
fileName.length());
}
Filef=newFile(outputDirectory+File.separator
+zipEntry.getName());
f.createNewFile();
InputStreamin=zipFile.getInputStream(zipEntry);
FileOutputStreamout=newFileOutputStream(f);
byte[]by=newbyte[1024];
intc;
while((c=in.read(by))!=-1){
out.write(by,0,c);
}
out.close();
in.close();
if(StringUtils.endsWith(zipEntry.getName(),".zip")){
Stringstr=outputDirectory+"/"+zipEntry.getName();
unZip(str,outputDirectory);
}
}
flag=true;
}
}catch(Exceptione){
log.error("",e);
}
returnflag;
}
/**
*创建目录
*
*@paramdirectory
*父目录
*@paramsubDirectory
*子目录
*/
privatestaticvoidcreateDirectory(Stringdirectory,StringsubDirectory){
Stringdir[];
Filefl=newFile(directory);
try{
if(subDirectory==""&&fl.exists()!=true)
fl.mkdir();
elseif(subDirectory!=""){
dir=subDirectory.replace('\\','/').split("/");
for(inti=0;i<dir.length;i++){
FilesubFile=newFile(directory+File.separator+dir[i]);
if(subFile.exists()==false)
subFile.mkdir();
directory+=File.separator+dir[i];
}
}
}catch(Exceptione){
log.error("",e);
}
}
}
importjava.io.File;
importjava.util.ArrayList;
importjava.util.List;
/**
*
*@authorHLW
*@date2013-10-25
*/
publicclassFileUtil{
/**
*遍历指定文件夹下的文件
*
*@paramstrPath
*@return
*/
publicstaticListrefreshFileList(StringstrPath){
Listfilelist=newArrayList();
Filedir=newFile(strPath);
File[]files=dir.listFiles();
if(files!=null){
for(inti=0;i<files.length;i++){
if(files[i].isDirectory()){
refreshFileList(files[i].getAbsolutePath());
}else{
StringstrFileName=files[i].getAbsolutePath();
filelist.add(strFileName);
}
}
}
returnfilelist;
}
}