解压缩带有中文名文件的ZIP包

java.util.zip.ZipInputStream和java.util.zip.ZipOutputStream压缩和解压带有中文名文件的ZIP包时,会报如下异常:

java.lang.IllegalArgumentException
 at java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:293)
 at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:247)
 at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:74)
 at com.test.ZipTest.unZipAssetSouce(ZipTest.java:25)
 at com.test.ZipTest.main(ZipTest.java:14)

原因是JDK自带的ZIP工具类,默认读取文件名采用的是UTF-8编码,而对于那些文件名以非UTF-8编码的文件将不能正确读入,如利用WinZip压缩的ZIP包将不能处理有中文名的文件,其采用的是ASCII编码的,而在开发中往往会遇到这样的问题,下面给出解决方案:

提取JDK内部几个处理ZIP相关的类,Deflater.java,DeflaterOutputStream.java,InflaterInputStream.java,ZipConstants.java,ZipEntry.java,ZipInputStram.java,然后自定义一个CompresszZipFile.java 读入ZIP文件,源码:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class CompresszZipFile {
	
	static final int BUFFER = 2048;
	/**
	 * 读取ZIP文件,只适合于ZIP文件对于RAR文件无效,因为ZIP文件的压缩算法是公开的,而RAR不是
	 * @version 1.0
	 * @param zipfilepath:ZIP文件的路径,unzippath:要解压到的文件路径
	 */
	public void ReadZip(String zipfilepath,String unzippath){
		
		try {
			BufferedOutputStream bos = null;
			//创建输入字节流
			FileInputStream fis = new FileInputStream(zipfilepath);
			//根据输入字节流创建输入字符流
			BufferedInputStream bis = new BufferedInputStream(fis);
			//根据字符流,创建ZIP文件输入流
			ZipInputStream zis = new ZipInputStream(bis);
			//zip文件条目,表示zip文件
			ZipEntry entry;
			//循环读取文件条目,只要不为空,就进行处理
			while((entry=zis.getNextEntry())!=null){
				System.out.println("===="+entry.getName());
				int count ;
				byte date[] = new byte[BUFFER];
				//如果条目是文件目录,则继续执行
				if(entry.isDirectory()){
					continue;
				}else{
					int begin = zipfilepath.lastIndexOf("\\")+1;
					int end = zipfilepath.lastIndexOf(".")+1;
					String zipRealName = zipfilepath.substring(begin,end);
					bos = new BufferedOutputStream(new FileOutputStream(this.getRealFileName(unzippath+"\\"+zipRealName,entry.getName())));
					while((count=zis.read(date))!=-1){
						bos.write(date,0,count);
					}
					bos.flush();bos.close();
				}	
			}
			zis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private File getRealFileName(String zippath,String absFileName){
		String[] dirs = absFileName.split("/",absFileName.length());
		//创建文件对象 
		File file = new File(zippath);
		if(dirs.length>1){
			for(int i=0;i<dirs.length-1;i++){
				//根据file抽象路径和dir路径字符串创建一个新的file对象,路径为文件的上一个目录
				file = new File(file,dirs[i]);
			}
		}
		if(!file.exists()){
			file.mkdirs();
		}
		file = new File(file,dirs[dirs.length-1]);
		return file;
	}
}

然后建立一个测试类 ZipTest.java,源码:

import com.zip.tool.CompresszZipFile;

public class ZipTest {

	public static void main(String args[]){
		
		CompresszZipFile compress = new CompresszZipFile();
		compress.ReadZip("D:\\Android\\workspace\\Test\\word.zip", "D:\\test");
	}
}

测试运行OK 。。。

为方便大家测试,将以上相关类打成一个jar包分享给大家!!(以上源码有些来源于网络)

http://download.csdn.net/download/adreamer_bj/3745253

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值