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