zip格式文件編碼檢測


解壓后文件名亂碼

由於zip格式文件無編碼存儲的結構,因此解壓時無法知道原先的編碼。

當解壓zip格式文件時使用的編碼和原編碼不一致時,就可能會出現解壓后文件名亂碼問題。

猜測編碼

基於上述問題,需要對zip格式文件所使用的編碼進行猜測。

筆者使用基於統計學原理的 juniversalchardet 庫來猜測編碼,下面是maven依賴坐標。

<dependency>
    <groupId>com.googlecode.juniversalchardet</groupId>
    <artifactId>juniversalchardet</artifactId>
    <version>1.0.3</version>
</dependency>

下面是一個簡單的例子,只需要提供待猜測文本的字節數據即可。

UniversalDetector detector = new UniversalDetector(null);
String text = "這是一段測試文本";
byte[] buf = text.getBytes("GB18030");
detector.handleData(buf, 0, buf.length);
detector.dataEnd();
System.out.println(detector.getDetectedCharset()); // GB18030

zip格式文件結構

zip格式文件的結構如下(具體解析見其他文章),這里需要其中的 CENTRAL_DIRCETORY_HEADER 區域,該區域存儲zip里所有的文件及文件夾的名稱。

|LOCAL_FILE_HEADER|
|EXTRA_LOCAL_HEADER|
|CENTRAL_DIRCETORY_HEADER|
|END_OF_CENTRAL_DIRCETORY_RECORD|

利用Apache Compress庫獲取名稱字節數據

筆者一般推薦使用 Apache Compress 庫來處理zip格式文件,可以使用 ZipArchiveEntry.getRawName 方法來獲取名稱的字節數據。

下面是檢測zip格式文件編碼的例子,其中為了加快速度忽略解析Local file header區域。

public String detectCharset(File file) throws IOException {
    // Ignore resolve local file header to improve rate.
    ZipFile zipFile = new ZipFile(file, StandardCharsets.UTF_8.name(), true, false);
    Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
    UniversalDetector detector = new UniversalDetector(null);

    while (entries.hasMoreElements()) {
        ZipArchiveEntry entry = entries.nextElement();
        byte[] buf = entry.getRawName();  // Get the byte data of file name.
        detector.handleData(buf, 0, buf.length);
    }
    detector.dataEnd();
    return detector.getDetectedCharset();
}

下面是Apache Compress庫的依賴坐標。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.21</version>
</dependency>

注意事項

數據量越大 juniversalchardet 庫檢測編碼就越准確,反之可能得到空結果或者不准確的編碼。

例如猜測編碼章節中讓 text="中文" ,最后輸出的結果是 KOI8-R

為此實際使用中要根據業務場景來做限定,比方說系統面向的用戶只可能是中文用戶,那么當出現 KOI8-R 這種斯拉夫文字的編碼時應當限定為中文的 GB18030 編碼(數據量小時GB18030非常大概率會被檢測成KOI8-R)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM