日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java zip malformed_关于Java解压文件的一些坑及经验分享(MALFORMED异常)

發(fā)布時(shí)間:2024/10/8 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java zip malformed_关于Java解压文件的一些坑及经验分享(MALFORMED异常) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)于Java解壓文件的一些坑及經(jīng)驗(yàn)分享

就在本周, 測試人員找到我說現(xiàn)上的需求文檔(zip格式的)無法預(yù)覽了, 讓我?guī)兔纯丛趺椿厥隆?/p>

這個(gè)功能也并不是我做的, 于是我便先看看線上日志有沒有什么錯(cuò)誤,果不其然, 后臺果然報(bào)錯(cuò)了。

java.lang.IllegalArgumentException:MALFORMED

at?java.util.zip.ZipCoder.toString(ZipCoder.toString:58)

...

異常大致是這樣,前臺無法預(yù)覽需求文檔的原因是該zip文件解壓失敗了。

首先網(wǎng)上查了下這個(gè)異常的原因, 都說是因?yàn)榫幋a的問題, 要求將UTF-8改成GBK就可以了。

然后定位代碼, 看到有一個(gè)方法: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("\\*",?"/");

;????????????//判斷路徑是否存在,不存在則創(chuàng)建文件路徑

File?file?=?new?File(outPath.substring(0,?outPath.lastIndexOf('/')));????????????if?(!file.exists())?{

file.mkdirs();

}????????????//判斷文件全路徑是否為文件夾,如果是上面已經(jīng)上傳,不需要解壓

if?(new?File(outPath).isDirectory())?{????????????????continue;

}????????????//輸出文件路徑信息

LOG.info("解壓文件的當(dāng)前路徑為:{}",?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文件出錯(cuò)",?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下來 然后本地調(diào)試下, 發(fā)現(xiàn)在第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才會進(jìn)入if邏輯才會拋錯(cuò)?果然如網(wǎng)上所說, 將編碼格式改為GBK即可。

ZipCoder這個(gè)類似src.zip包中的, 既然這里做了check當(dāng)然會有它的道理, 單純的改為GBK來解決這個(gè)bug顯然是不合理的。

于是便要換種思路了, 線上有些zip是仍然可以預(yù)覽的。 我將線上的zip文件解壓后, 在自己電腦重新打個(gè)包(我用的是好壓), 然后又運(yùn)行了上述代碼, 竟然解壓成功?? 這是為什么? 于是上網(wǎng)上找了一下, 果然找到了答案:Windows 壓縮的時(shí)候使用的是系統(tǒng)的編碼 GB2312,而 Mac 系統(tǒng)默認(rèn)的編碼是 UTF-8,于是出現(xiàn)了亂碼。

最后去問了上傳的同事, 他是在Windows下用的winRar上傳的(看來不同的解壓工具還不同)。

好了, 問題基本定位到了, 這里就要想著怎么解決了。

又是一通找, 終于:Apache commons-compress 解壓 zip 文件是件很幸福的事,可以解決 zip 包中文件名有中文時(shí)跨平臺的亂碼問題,不管文件是在 Windows 壓縮的還是在 Mac,Linux 壓縮的,解壓后都沒有再出現(xiàn)亂碼問題了。

看到這里基本上問題就要解決了, 于是開始使用apache的commons-compress了, 下面直接上代碼, 代碼是基于上面代碼進(jìn)行改造的:

首先引入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("解壓文件的當(dāng)前路徑為:{}",?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())?{????????????//?說明只有一個(gè)文件夾

FileUtils.copyDirectory(files[0],?pathFile);????????????//免得刪除錯(cuò)誤,?刪除的文件必須在/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文件出錯(cuò)",?e);

}

}private?static?ZipArchiveInputStream?getZipFile(File?zipFile)?throws?Exception?{????return?new?ZipArchiveInputStream(new?BufferedInputStream(new?FileInputStream(zipFile)));

}

到了這里就大功告成了, 原先自己遇到這個(gè)問題時(shí)百度了一圈, 解決方案大都是改編碼格式為GBK, 但那也只是治標(biāo)不治本的方法, 解壓的坑就講這么多, 后續(xù)有新的坑還會繼續(xù)總結(jié)出來的。

總結(jié)

以上是生活随笔為你收集整理的java zip malformed_关于Java解压文件的一些坑及经验分享(MALFORMED异常)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。