欢迎访问 生活随笔!

ag凯发k8国际

当前位置: ag凯发k8国际 > 编程语言 > java >内容正文

java

java zip malformed-ag凯发k8国际

发布时间:2024/10/8 java 0 豆豆
ag凯发k8国际 收集整理的这篇文章主要介绍了 java zip malformed_关于java解压文件的一些坑及经验分享(malformed异常) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

关于java解压文件的一些坑及经验分享

就在本周, 测试人员找到我说现上的需求文档(zip格式的)无法预览了, 让我帮忙看看怎么回事。

这个功能也并不是我做的, 于是我便先看看线上日志有没有什么错误,果不其然, 后台果然报错了。

java.lang.illegalargumentexception:malformed

at java.util.zip.zipcoder.tostring(zipcoder.tostring:58)

...

异常大致是这样,前台无法预览需求文档的原因是该zip文件解压失败了。

首先网上查了下这个异常的原因, 都说是因为编码的问题, 要求将utf-8改成gbk就可以了。

然后定位代码, 看到有一个方法:unzip()public static void unzip(file zipfile, string descdir) {    try {

file pathfile = new file(descdir);        if (!pathfile.exists()) {

pathfile.mkdirs();

}

zipfile zip = getzipfile(zipfile);        for (enumeration entries = zip.entries(); entries.hasmoreelements(); ) {

zipentry entry = (zipentry) entries.nextelement();

string zipentryname = entry.getname();            if (stringutils.isnotblank(pre)) {

zipentryname = zipentryname.substring(pre.length());

}

inputstream in = zip.getinputstream(entry);

string outpath = (descdir   "/"   zipentryname).replaceall("\\*", "/");

;            //判断路径是否存在,不存在则创建文件路径

file file = new file(outpath.substring(0, outpath.lastindexof('/')));            if (!file.exists()) {

file.mkdirs();

}            //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压

if (new file(outpath).isdirectory()) {                continue;

}            //输出文件路径信息

log.info("解压文件的当前路径为:{}", outpath);

outputstream out = new fileoutputstream(outpath);

ioutils.copy(in, out);

in.close();

out.close();

}

zip.close();

log.info("******************解压完毕********************");

} catch (exception e) {

log.error("[unzip] 解压zip文件出错", e);

}

}private static zipfile getzipfile(file zipfile) throws exception {

zipfile zip = new zipfile(zipfile, charset.forname("utf-8"));

enumeration entries = zip.entries();    while (entries.hasmoreelements()) {        try {

entries.nextelement();

zip.close();

zip = new zipfile(zipfile, charset.forname("utf-8"));            return zip;

} catch (exception e) {

zip = new zipfile(zipfile, charset.forname("gbk"));            return zip;

}

}    return zip;

}

于是便将线上的zip文件down下来 然后本地调试下, 发现在第9行中抛出了异常, 如下代码:zipentry entry = (zipentry) entries.nextelement();

再由最开始的异常日志找到zipcoder中的58行:string tostring(byte[] ba, int length) {

charsetdecoder cd = decoder().reset();    int len = (int)(length * cd.maxcharsperbyte());    char[] ca = new char[len];    if (len == 0)        return new string(ca);    // utf-8 only for now. other arraydeocder only handles

// codingerroraction.replace mode. zipcoder uses

// report mode.

if (isutf8 && cd instanceof arraydecoder) {        int clen = ((arraydecoder)cd).decode(ba, 0, length, ca);        if (clen == -1)    // malformed

throw new illegalargumentexception("malformed");        return new string(ca, 0, clen);

}

bytebuffer bb = bytebuffer.wrap(ba, 0, length);

charbuffer cb = charbuffer.wrap(ca);

coderresult cr = cd.decode(bb, cb, true);    if (!cr.isunderflow())        throw new illegalargumentexception(cr.tostring());

cr = cd.flush(cb);    if (!cr.isunderflow())        throw new illegalargumentexception(cr.tostring());    return new string(ca, 0, cb.position());

}

这里只有utf-8才会进入if逻辑才会抛错?果然如网上所说, 将编码格式改为gbk即可。

zipcoder这个类似src.zip包中的, 既然这里做了check当然会有它的道理, 单纯的改为gbk来解决这个bug显然是不合理的。

于是便要换种思路了, 线上有些zip是仍然可以预览的。 我将线上的zip文件解压后, 在自己电脑重新打个包(我用的是好压), 然后又运行了上述代码, 竟然解压成功?? 这是为什么? 于是上网上找了一下, 果然找到了答案:windows 压缩的时候使用的是系统的编码 gb2312,而 mac 系统默认的编码是 utf-8,于是出现了乱码。

最后去问了上传的同事, 他是在windows下用的winrar上传的(看来不同的解压工具还不同)。

好了, 问题基本定位到了, 这里就要想着怎么解决了。

又是一通找, 终于:apache commons-compress 解压 zip 文件是件很幸福的事,可以解决 zip 包中文件名有中文时跨平台的乱码问题,不管文件是在 windows 压缩的还是在 mac,linux 压缩的,解压后都没有再出现乱码问题了。

看到这里基本上问题就要解决了, 于是开始使用apache的commons-compress了, 下面直接上代码, 代码是基于上面代码进行改造的:

首先引入pom文件:

org.apache.commons

commons-compress

1.8.1public static void main(string[] args) throws exception{

string path = "c:\\users\\isuzu\\desktop\\test.zip";

unzip(new file(path), "d:\\data",);

}public static void unzip(file zipfile, string descdir) {    try (ziparchiveinputstream inputstream = getzipfile(zipfile)) {

file pathfile = new file(descdir);        if (!pathfile.exists()) {

pathfile.mkdirs();

}

ziparchiveentry entry = null;        while ((entry = inputstream.getnextzipentry()) != null) {            if (entry.isdirectory()) {

file directory = new file(descdir, entry.getname());

directory.mkdirs();

} else {

outputstream os = null;                try {

os = new bufferedoutputstream(new fileoutputstream(new file(descdir, entry.getname())));                    //输出文件路径信息

log.info("解压文件的当前路径为:{}", descdir   entry.getname());

ioutils.copy(inputstream, os);

} finally {

ioutils.closequietly(os);

}

}

}        final file[] files = pathfile.listfiles();        if (files != null && files.length == 1 && files[0].isdirectory()) {            // 说明只有一个文件夹

fileutils.copydirectory(files[0], pathfile);            //免得删除错误, 删除的文件必须在/data/demand/目录下。

boolean isvalid = files[0].getpath().contains("/data/www/");            if (isvalid) {

fileutils.forcedelete(files[0]);

}

}

log.info("******************解压完毕********************");

} catch (exception e) {

log.error("[unzip] 解压zip文件出错", e);

}

}private static ziparchiveinputstream getzipfile(file zipfile) throws exception {    return new ziparchiveinputstream(new bufferedinputstream(new fileinputstream(zipfile)));

}

到了这里就大功告成了, 原先自己遇到这个问题时百度了一圈, ag凯发k8国际的解决方案大都是改编码格式为gbk, 但那也只是治标不治本的方法, 解压的坑就讲这么多, 后续有新的坑还会继续总结出来的。

总结

以上是ag凯发k8国际为你收集整理的java zip malformed_关于java解压文件的一些坑及经验分享(malformed异常)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得ag凯发k8国际网站内容还不错,欢迎将ag凯发k8国际推荐给好友。

网站地图