java.util.zip解压问题

qwchung 2003-11-07 12:53:22
代码如下:
import java.io.*;
import java.util.zip.*;

public class UnZip {
static final int BUFFER = 2048;
public static void main (String argv[]) {
try {
BufferedOutputStream dest = null;
FileInputStream fis = new
FileInputStream("test.zip");
//System.out.println(fis.toString());
ZipInputStream zis = new
ZipInputStream(new BufferedInputStream(fis));

ZipEntry entry=null;
while((entry = zis.getNextEntry())!= null)
//好象就是这里的
//zis.getNextEntry()方法出了错,但不知道为什么?
{
System.out.println("Extracting: " +entry);
int count;
byte data[] = new byte[BUFFER];
// write the files to the disk
FileOutputStream fos = new
FileOutputStream(entry.getName());
dest = new
BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER))
!= -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
} catch(Exception e) {
e.getMessage();
e.printStackTrace();

}
}
}
执行后报的异常为:
java.lang.IllegalArgumentException
at java.util.zip.ZipInputStream.getUTF8String(ZipInputStream.java:291)
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:230)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:75)
at myzip.UnZip.main(UnZip.java:27)

请高手指点!!!
...全文
483 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
zjcxx 2004-02-20
  • 打赏
  • 举报
回复
多个文件的压缩好象有错误
qwchung 2003-11-07
  • 打赏
  • 举报
回复
靠,开始有中文,后来我只是把zip文件给修改了一下,但一直都是如此错误,刚才我把jbuilder给重新启动了一次,结果就ok了,看来是jbuilder的bug,谢谢两位!
tele 2003-11-07
  • 打赏
  • 举报
回复
2.执行压缩的代码://这个就有必要看明白了
package xxx;
import java.io.*;
import java.util.*;
import java.util.zip.*;
public class OperFile{
FileOutputStream fos;
CheckedOutputStream csum;
ZipOutputStreamE out;//新定义的
int index;
public void zipFold(File unzipf,File zipf) throws Exception{//unzipf是待压缩
的文件,zipf是压缩后的文件
if(!unzipf.exists())
return;
else{
fos=new FileOutputStream(zipf);
csum=new CheckedOutputStream(fos,new Adler32());
out=new ZipOutputStreamE(new BufferedOutputStream(csum));
index=unzipf.toString().lastIndexOf("\\");
zipF(unzipf);
out.close();
return;
}
} zipFold()定义完毕
public void zipF(File f) throws Exception{
if(f.isFile()){
FileInputStream in=new FileInputStream(f);
String etr=f.toString().substring(index+1);
out.putNextEntry(new ZipEntry(etr));
byte[] b=new byte[4096];
int byte_read;
while((byte_read=in.read(b))!=-1)
out.write(b,0,byte_read);
in.close();
return;
}
else{
ZipEntry ze=new ZipEntry(f.toString().substring(index+1)+"/");
out.putNextEntry(ze);
File[] fs=f.listFiles();
if(fs!=null)
for(int i=0;i<fs.length;i++)
zipF(fs[i]);
}
}//zipF()定义完毕

public static void main(String args[]){
if(args.length!=2)
System.exit();
else{
OperFile opf=new OperFile();
opf.zipFold(new File(args[0]),new File(args[1]));
}
}
}

--

※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.82.193]

tele 2003-11-07
  • 打赏
  • 举报
回复
public void finish()
throws IOException
{
ensureOpen();
if(finished)
{
return;
}
if(entry != null)
{
closeEntry();
}
if(entries.size() < 1)
{
throw new ZipException("ZIP file must have at least one entry");

}
long l = written;
for(Enumeration enumeration = entries.elements(); enumeration.hasMor
eElements(); writeCEN((ZipEntry)enumeration.nextElement())) { }
writeEND(l, written - l);
finished = true;
}
public void close()
throws IOException
{
finish();
super.out.close();
closed = true;
}
private void writeLOC(ZipEntry zipentry)
throws IOException
{
writeInt(0x4034b50L);
writeShort(version);
writeShort(flag);
writeShort(zipentry.getMethod());
writeInt(zipentry.getTime());
if((flag & 8) == 8)
{
writeInt(0L);
writeInt(0L);
writeInt(0L);
} else
{
writeInt(zipentry.getCrc());
writeInt(zipentry.getCompressedSize());
writeInt(zipentry.getSize());
}
byte abyte0[] = zipentry.getName().getBytes("gb2312");
writeShort(abyte0.length);
writeShort(zipentry.getExtra() != null ? zipentry.getExtra().length
: 0);
writeBytes(abyte0, 0, abyte0.length);
if(zipentry.getExtra() != null)
{
writeBytes(zipentry.getExtra(), 0, zipentry.getExtra().length);
}
locoff = written;
}
private void writeEXT(ZipEntry zipentry)
throws IOException
{
writeInt(0x8074b50L);
writeInt(zipentry.getCrc());
writeInt(zipentry.getCompressedSize());
writeInt(zipentry.getSize());
}
private void writeCEN(ZipEntry zipentry)
throws IOException
{
writeInt(0x2014b50L);
writeShort(version);
writeShort(version);
writeShort(flag);
writeShort(zipentry.getMethod());
writeInt(zipentry.getTime());
writeInt(zipentry.getCrc());
writeInt(zipentry.getCompressedSize());
writeInt(zipentry.getSize());
byte abyte0[] = zipentry.getName().getBytes("gb2312");
writeShort(abyte0.length);
writeShort(zipentry.getExtra() != null ? zipentry.getExtra().length
: 0);
byte abyte1[];
if(zipentry.getComment() != null)
{
abyte1 = getUTF8Bytes(zipentry.getComment());
writeShort(abyte1.length);
} else
{
abyte1 = null;
writeShort(0);
}
writeShort(0);
writeShort(0);
writeInt(0L);
writeInt(offset);
writeBytes(abyte0, 0, abyte0.length);
if(zipentry.getExtra() != null)
{
writeBytes(zipentry.getExtra(), 0, zipentry.getExtra().length);
}
if(abyte1 != null)
{
writeBytes(abyte1, 0, abyte1.length);
}
}
private void writeEND(long l, long l1)
throws IOException
{
writeInt(0x6054b50L);
writeShort(0);
writeShort(0);
writeShort(entries.size());
writeShort(entries.size());
writeInt(l1);
writeInt(l);
if(comment != null)
{
byte abyte0[] = getUTF8Bytes(comment);
writeShort(abyte0.length);
writeBytes(abyte0, 0, abyte0.length);
} else
{
writeShort(0);
}
}
private void writeShort(int i)
throws IOException
{
OutputStream outputstream = super.out;
outputstream.write(i >>> 0 & 0xff);
outputstream.write(i >>> 8 & 0xff);
written += 2L;
}
private void writeInt(long l)
throws IOException
{
OutputStream outputstream = super.out;
outputstream.write((int)(l >>> 0 & 255L));
outputstream.write((int)(l >>> 8 & 255L));
outputstream.write((int)(l >>> 16 & 255L));
outputstream.write((int)(l >>> 24 & 255L));
written += 4L;
}
private void writeBytes(byte abyte0[], int i, int j)
throws IOException
{
super.out.write(abyte0, i, j);
written += j;
}
private static byte[] getUTF8Bytes(String s)
{
char ac[] = s.toCharArray();
int i = ac.length;
int j = 0;
for(int k = 0; k < i; k++)
{
char c = ac[k];
if(c <= '\177')
{
j++;
} else
if(c <= '\u07FF')
{
j += 2;
} else
{
j += 3;
}
}
byte abyte0[] = new byte[j];
int l = 0;
for(int i1 = 0; i1 < i; i1++)
{
char c1 = ac[i1];
if(c1 <= '\177')
{
abyte0[l++] = (byte)c1;
} else
if(c1 <= '\u07FF')
{
abyte0[l++] = (byte)(c1 >> 6 | 0xc0);
abyte0[l++] = (byte)(c1 & 0x3f | 0x80);
} else
{
abyte0[l++] = (byte)(c1 >> 12 | 0xe0);
abyte0[l++] = (byte)(c1 >> 6 & 0x3f | 0x80);
abyte0[l++] = (byte)(c1 & 0x3f | 0x80);
}
}
return abyte0;
}
}

qwchung 2003-11-07
  • 打赏
  • 举报
回复
开始是有中文,我想到可能是中文名字引起的,但改成非中文名字后,还是依然提示这个错误;你说在你机器上就可以正常运行,怎么在我这就不行?就是用这个zipinputstream不行,我用zipfile来解压缩就可以正常运行,真是要晕了
tele 2003-11-07
  • 打赏
  • 举报
回复
附:相关源代码
1.ZipOutputStreamE//这个没必要看得很明白,只要搞清楚和ZipOutputStream的区别
//以及为什么要这样改动就行了
package xxx;
import java.io.*;
import java.util.*;
import java.util.zip.*;
// Referenced classes of package xxx:
// DeflaterOutputStream, Deflater, CRC32, ZipException,
// ZipEntry, ZipConstants
public class ZipOutputStreamE extends DeflaterOutputStream
implements ZipConstants
{
private ZipEntry entry;
private Vector entries;
private Hashtable names;
private CRC32 crc;
private long written;
private long locoff;
private String comment;
private int method;
private boolean finished;
private boolean closed;
public static final int STORED = 0;
public static final int DEFLATED = 8;
public int flag;//代替zipentry中的flag
public int version;//代替zipentry中的version
public long offset;//代替zipentry中的offset
private void ensureOpen()
throws IOException
{
if(closed)
{
throw new IOException("Stream closed");
} else
{
return;
}
}
public ZipOutputStreamE(OutputStream outputstream)
{
super(outputstream, new Deflater(-1, true));
entries = new Vector();
names = new Hashtable();
crc = new CRC32();
locoff = 0L;
method = 8;
closed = false;
}
public void setComment(String s)
{
if(s.length() > 65535)
{
throw new IllegalArgumentException("invalid ZIP file comment");
} else
{
comment = s;
return;
}
}
public void setMethod(int i)
{
if(i != 8 && i != 0)
{
throw new IllegalArgumentException("invalid compression method")
;
} else
{
method = i;
return;
}
}
public void setLevel(int i)
{
super.def.setLevel(i);
}
public void putNextEntry(ZipEntry zipentry)
throws IOException
{
ensureOpen();
if(entry != null)
{
closeEntry();
}
if(zipentry.getTime() == -1L)
{
zipentry.setTime(System.currentTimeMillis());
}
if(zipentry.getMethod() == -1)
{
zipentry.setMethod(method);
}
switch(zipentry.getMethod())
{
case 8: // '\b'
if(zipentry.getSize() == -1L || zipentry.getCompressedSize() ==
-1L || zipentry.getCrc() == -1L)
{
flag = 8;
} else
if(zipentry.getSize() != -1L && zipentry.getCompressedSize() !=
-1L && zipentry.getCrc() != -1L)
{
flag = 0;
} else
{
throw new ZipException("DEFLATED entry missing size, compres
sed size, or crc-32");
}
version = 20;
break;
case 0: // '\0'
if(zipentry.getSize() == -1L)
{
zipentry.setSize(zipentry.getCompressedSize());
} else
if(zipentry.getCompressedSize() == -1L)
{
zipentry.setCompressedSize(zipentry.getSize());
} else
if(zipentry.getSize() != zipentry.getCompressedSize())
{
throw new ZipException("STORED entry where compressed != unc
ompressed size");
}
if(zipentry.getSize() == -1L || zipentry.getCrc() == -1L)
{
throw new ZipException("STORED entry missing size, compresse
d size, or crc-32");
}
version = 10;
flag = 0;
break;
default:
throw new ZipException("unsupported compression method");
}
offset = written;
writeLOC(zipentry);
if(names.put(zipentry.getName(), zipentry) != null)
{
throw new ZipException("duplicate entry: " + zipentry.getName())
;
} else
{
entries.addElement(zipentry);
entry = zipentry;
return;
}
}
public void closeEntry()
throws IOException
{
ensureOpen();
ZipEntry zipentry = entry;
if(zipentry != null)
{
switch(zipentry.getMethod())
{
case 8: // '\b'
super.def.finish();
for(; !super.def.finished(); deflate()) { }
if((flag & 8) == 0)
{
if(zipentry.getSize() != (long)super.def.getTotalIn())
{
throw new ZipException("invalid entry size (expected
" + zipentry.getSize() + " but got " + super.def.getTotalIn() + " bytes)");

}
if(zipentry.getCompressedSize() != (long)super.def.getTo
talOut())
{
throw new ZipException("invalid entry compressed siz
e (expected " + zipentry.getCompressedSize() + " but got " + super.def.getTo
talOut() + " bytes)");
}
if(zipentry.getCrc() != crc.getValue())
{
throw new ZipException("invalid entry CRC-32 (expect
ed 0x" + Long.toHexString(zipentry.getCrc()) + " but got 0x" + Long.toHexStr
ing(crc.getValue()) + ")");
}
} else
{
zipentry.setSize(super.def.getTotalIn()) ;
zipentry.setCompressedSize(super.def.getTotalOut()) ;
zipentry.setCrc(crc.getValue()) ;
writeEXT(zipentry);
}
super.def.reset();
written += zipentry.getCompressedSize();
break;
case 0: // '\0'
if(zipentry.getSize() != written - locoff)
{
throw new ZipException("invalid entry size (expected " +
zipentry.getSize() + " but got " + (written - locoff) + " bytes)");
}
if(zipentry.getCrc() != crc.getValue())
{
throw new ZipException("invalid entry crc-32 (expected 0
x" + Long.toHexString(zipentry.getCrc()) + " but got 0x" + Long.toHexString(
crc.getValue()) + ")");
}
break;
default:
throw new InternalError("invalid compression method");
}
crc.reset();
entry = null;
}
}
public synchronized void write(byte abyte0[], int i, int j)
throws IOException
{
ensureOpen();
if(i < 0 || i > abyte0.length || j < 0 || i + j > abyte0.length || i
+ j < 0)
{
throw new IndexOutOfBoundsException();
}
if(j == 0)
{
return;
}
if(entry == null)
{
throw new ZipException("no current ZIP entry");
}
switch(entry.getMethod())
{
case 8: // '\b'
super.write(abyte0, i, j);
break;
case 0: // '\0'
written += j;
if(written - locoff > entry.getSize())
{
throw new ZipException("attempt to write past end of STORED
entry");
}
super.out.write(abyte0, i, j);
break;
default:
throw new InternalError("invalid compression method");
}
crc.update(abyte0, i, j);
}

tele 2003-11-07
  • 打赏
  • 举报
回复
如果是中文的问题,你可以看看这篇文章,相信对你有帮助

转帖自清华bbs有一些代码由于粘贴的格式不对,需要调整一下,不过很快就搞定。我已经测试过了,没问题
发信人: zengcheng (我是曾诚), 信区: Java
标 题: 用ZipOutputStream压缩中文文件夹完全解决方案
发信站: BBS 水木清华站 (Wed Apr 9 23:45:18 2003), 转信

用ZipOutputStream类压缩中文文件名的文件(夹)完全解决方案


在刚开始直接用ZipOutputStream类压缩文件的时候,英文文件名的文件是完全没
有问题的,中文文件名就不行,表现在:
1.如果是文件,那么文件名就成了乱码,而文件内容完好; 这很容易理解,因为
ZipOutputStream对文件内容的处理和OutputStream完全一样,除了写的bytes
是压缩过的bytes这一点除外.
2.如果是文件夹,那就彻底糟了,不光文件夹的名字成了乱码,并且此文件夹下面的
东西全部消失.
以上两点说明:ZipOutputStream在设计的时候根本没有考虑文件名是中文的情况.
于是想到改ZipOutputStream的源代码;
用Cavaj反编译JAVA_HOME/jre/lib/rt.jar中的java.util.zip.ZipOutputStream类的源
代码,发现对文件名的处理有这样两段代码,:
line291: byte abyte0[] = getUTF8Bytes(zipentry.name);
//在方法private void writeLOC(ZipEntry zipentry)中
line322: byte abyte0[] = getUTF8Bytes(zipentry.name);
//在方法private void writeCEN(ZipEntry zipentry)中
注意:由于jdk或反编译工具的差异,具体的行数可能有差别
不管这两个方法的具体作用,只看这两段代码
在这两段代码中:
zipentry.name是ZipEntry类的一个访问权限为缺省的String域.因为用ZipOutput-
Stream压缩文件时,每个文件或文件夹都对应着一个ZipEntry,所有可以把
zipentry.name看作是文件(夹)的名字.我们再看ZipOutputStream是怎么处理这个
name的:
byte abyte0[] = getUTF8Bytes(zipentry.name);
可以看到,他把zipentry.name也就是我们关心的文件名用getUTF8Bytes(String s)
这个方法处理了一下,然后返回一个byte型的数组给abyte0.查了一下源文件,
getUTF8Bytes(String s)这个方法是个private方法,他将s中的每一个unicode字符
转换为UTF-8的字节后返回一个字节数组.问题会不会出在这个转换上呢?
于是,我试着将这两段代码改为:
line291: byte abyte0[] = zipentry.name.getBytes("gb2312");
line322: byte abyte0[] = zipentry.name.getBytes("gb2312");
编译这段代码,然后将JAVA_HOME/jre/lib/rt.jar中的java.util.zip.ZipOutputStream
-.class文件替换为新编译的文件(WinRar应该提供了直接更新压缩文件内的文件的
方法,但本人很土,倒腾了半天也倒腾不出来,因此是先解压rt,jar,然后替换再压缩,
很笨吧!),再试着用以前的代码压缩一个中文文件夹,用WinRar打开,成功了!
短暂的兴奋过后,又想到一个问题:如果要在另外一台机器上也实现这个功能,岂不
又要改那台机器的rt.jar?这样弄是很麻烦的,或者说是不可行的.说白了,改jdk的源代
码除了自己玩玩以外,还真没觉得有什么用.于是又想有没有其他的方法.
我想,既然改一个文件嫌麻烦,何不自己重新再做一个zip包,以后要用到压缩的时候用
这个新的zip包就行了,不用java.util.zip包,就跟用bean一样,这样多方便!
于是我把zip包里面的所有.class文件反编译为.java文件(ZipOutputStream是改动
后的),然后把文件头上的package语句改成"package xxx;","xxx"是我自己定义的包名.
接下来全部编译,就生成了一个完全拷贝 java.util.zip包的新包,只有一点点不一样.接
着,兴冲冲地把执行压缩的代码前面的"import java.util.zip*;"换成"import xxx;",心
里还在想,java.util.zip,去死吧!结果一运行,给我一个打击:UnsatisfiedLinkError!
查了一下jdk文档,这个error是在loadlibrary的时候抛出的,原来java.util.zip还用到
了native方法,这下完蛋了:.class文件可以反编译,.dll我可搞不定.顺便问一句,谁能搞定
.dll啊?
还不死心:ZipOutputStream并没有用到native方法,是别的类用到的,那我只把
java.util.zip包里面的ZipOutputStream一个类放到新包里面,其他类不动不就行了吗?
于是把xxx包里面的其它类都删掉,只留下一个ZipOutputstream,并且改名为
ZipOutputStreamE,因为以后压缩文件的时候还是用到java.util.zip包,xxx包和java.
util.zip包里面都有ZipOutputstream的话就要写全名,很麻烦.
javac,发现又有大麻烦:
麻烦1: public class ZipOutputStreamE extends DeflaterOutputStream
implements ZipConstants
这个ZipConstants是java.util.zip包的一个class,访问控制符为缺省,不是public,也就
是说只有同一包的类才能访问,而现在ZipOutputStreamE已经是package xxx了;
麻烦2: ZipOutputStreamE的代码大量访问到了ZipEntry类的一些属性,而这些属性
的访问控制符都是缺省的,跟上面的情况一样,都是只有同一个包的类才能访问;
大量脑细胞死亡后,麻烦被干掉:
麻烦1的死: 反编译了ZipConstants,发现里面都是定义的一些常量,没有方法,于是把
java.uti.zip包里面的ZipConstants类反编译,然后把文件头上的"package java.util.
zip;"改为"package xxx;",编译后放到xxx里面,这下又成一家人了;
麻烦2的死:虽然要用到的ZipEntry的属性都是缺省的,但是ZipEntry类提供了读写这些
属性的public方法,比如ZipEntry有属性long time,对应着就有public long getTime()
和public void setTime(long l),于是,需要涉及到time属性的地方就可以用这两个方法
代替,比如:if(zipentry.time == -1L)可改为if(zipentry.getTime() == -1L)
zipentry.time=System.currentTimeMillis();
可改为zipentry.setTime(System.currentTimeMillis());
但是有三个例外,这就是ZipEntry的int flag, int version和 long offset三个属性.Z
ipEntry没有提供这三个属性的读写方法,怎么办?我查了一下zip包的源代码,发现这三个
属性用处不大,总共只在三个类里出现过:ZipEntry,ZipOutputStream和ZipInputStream,
其中ZipEntry
只是定义了这三个属性,并没有用到,说得明白点就是这三个属性对于ZipEntry来说没用
,对zip包里面的其他类也没有用,因此,我在ZipOutputStreamE里面又定义了三个变量
int flag, int version和 long offset,来代替zipentry.flag,zipentry.version和zi
pentry.offset.
这次改动之后,彻底成功了.

tele 2003-11-07
  • 打赏
  • 举报
回复
test.zip里面的文件名是不是包含中文?
qwchung 2003-11-07
  • 打赏
  • 举报
回复
我用的是win2000 server,我觉得我写的程序也没什么问题;我估计和路径没什么关系可能,这个错误并不是找不到zip文件,是能找到文件的,关键就是getnextentry()这个方法执行有问题
okwuzhijun 2003-11-07
  • 打赏
  • 举报
回复
你用的是什么操作系统,我在win2000 pro 下一切正常啊。
你把test.zip写成绝对路径看看,例如:c:/test.zip

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧