2016年4月11日 星期一

實測最準確, 用cpdetector偵測unicode utf-8 big5 gbk 等檔案編碼

當讀取一個純文字檔時, 它的編碼為何, 一般是無法知道的, 這也造成許多亂碼的問題, 有些文件的檔首有標記可進行判斷, 事情會比較簡單, 但遇到無標記可判斷的文件, 要知道其編碼, 就有些麻煩了.
cpdetector一個可以自動檢測檔案編碼格式的項目, 經過實測其準確度頗高, 它是按照「誰最先得到探測結果,就以該結果為準」傳回探測的文件編碼。 它可以給一個網址, 來判斷該網址所指向的網頁編碼, 也可以給一個檔名, 用以判斷該文檔的編碼. cpDetector是採用統計原理,探測的結果並非完全正確。

以下只能判斷有標記的unicode相關的檔案, big5 gbk 等判斷不出來
    private String getCharset(String fileName) throws IOException {

        BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
                fileName));
        int p = (bin.read() << 8) + bin.read();

        String code = null;

        switch (p) {
        case 0xefbb:
            code = "UTF-8";
            break;
        case 0xfffe:
            code = "Unicode";
            break;
        case 0xfeff:
            code = "UTF-16BE";
            break;
        }
        return code;
    }


以下是一段使用cpdetector 的 java判斷文件的範例
public static String getTextCode(File f) {

CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
//ParsingDetector可用於檢查HTML、XML等文件的編碼,false不顯示探測過程的詳細信息。
// detector.add(new ParsingDetector(false));

//為了增加準確性,採用多個探測器,增加探測器不會增加執行時間,
//因為detector按照「誰最先返回非空的探測結果,就以該結果為準」不會繼續執行其他探測.

// 如果是unicode的文件, ByteOrderMarkDetector可快速檢測
detector.add(new ByteOrderMarkDetector());

//JChardetFacade封裝了由Mozilla組織提供的JChardet,它可以完成大多數文件的編碼
//測定。所以,一般有了這個探測器就可滿足大多數項目的要求,如果你還不放心,可以
//再多加幾個探測器,比如下面的ASCIIDetector、UnicodeDetector等      
detector.add(JChardetFacade.getInstance());
detector.add(ASCIIDetector.getInstance());
detector.add(UnicodeDetector.getInstance());

java.nio.charset.Charset charset = null;
try {
charset = detector.detectCodepage(f.toURI().toURL());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

String a = charset.name();
return a;
}


cpdetector會用到三個JAR包:antlr.jar、chardet.jar和cpdetector.jar


如果需要對網址進行網頁編碼判斷, 使用detector.detectCodepage指令, 請參考以下:
https://segmentfault.com/a/1190000004408835

  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP