利用java.nio.charset.CharsetDecoder自動識別字符集


研究了在網上能找到的自動識別字符集的辦法,有效的就是利用第三方類庫jchardet。也有用cpdetector,其實也是利用jchardet。偶然發現jdk的java.nio.charset.CharsetDecoder可以用來識別字符集。

一、原理

一般用兩種方法構建InputStreamReader:

InputStreamReader reader = new InputStreamReader(in, charsetName);

或者

InputStreamReader reader = new InputStreamReader(in, charset);

如果charset不匹配,則輸出亂碼。

還有一種構建方法,即利用CharsetDecoder:

CharsetDecoder cd = charset.newDecoder();
InputStreamReader reader = new InputStreamReader(in, cd);

這時如果不匹配,則拋出異常:

java.nio.charset.MalformedInputException: Input length = 1
    at java.nio.charset.CoderResult.throwException(CoderResult.java:277)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:338)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
        ....

這樣,就可以用作字符集探測。

二、AutoCharsetReader的使用

AutoCharsetReader是根據上述原理,參考InputStreamReader而寫成的類,繼承Reader,可以看作為Charset自適應的InputStreamReader。

AutoCharsetReader ar= new AutoCharsetReader(in);
char c = ar.read();
...
char[] cbuf = new char[2000];
ar.read(cbuf);
...
BufferedReader br = new BufferedReader(ar);
br.readLine();
...

再比如Lucene創建全文索引的TextField需要Reader參數,可以直接利用這個類:

Field field = new TextField("content", new AutoCharsetReader(file));

讀完文件之后,可以得到文件的charset。注意,是讀完之后。

Charset charset = ar.charset();

三、備選字符集

因為采用多次嘗試的辦法來最終確定字符集,所以要提供備選。當前代碼提供的默認備選字符集如下:

    private final static String[] _defaultCharsets = {        
            "US-ASCII",
            "UTF-8",
            "GB2312", 
            "BIG5",
            "GBK",
            "GB18030",                
            "UTF-16BE", 
            "UTF-16LE", 
            "UTF-16",
            "UNICODE"};

也提供了更改備選字符集的方法。比如:

AutoCharsetReader ar = new AutoCharsetReader(in).setCharset("ascii", "utf-8", "gbk");

先后順序會影響探測結果。比如,如果GBK在GB2312之前,則檢測結果只能是GBK,不會是GB2312,因為GBK包含GB2312。

四、只作字符集檢測

可以只用作字符集檢測:

charset = AutoCharsetReader.quickDetect(file.toURI().toURL(), charsets);
or:
charset = AutoCharsetReader.deepDetect(file.toURI().toURL(), charsets, stops);

quickDetect只讀一個字符,適用於單字符集文件。對於html,可能需要全部讀完才知道charset,則使用deepDetect。其中參數charsets可以為null

如果一組文件,已知可能的字符集有“ascii”,“utf-8”,“gb2312”,和“gbk”,當檢測得知一個文件的字符集為“utf-8”或"gbk"的時候,可以馬上返回結果,無需繼續讀文件。這時可以把stops參數賦值為{"utf-8", "gbk"}。為null則需全部讀完。

五、其他

為提高效率,本類設有buffer,初選的字符集解碼失敗,不必重新讀取io。buffer大小默認為8192,對象構建時可以自定義buffer大小,若參數小於16,則設為16。

六、源代碼

http://download.csdn.net/detail/u012994553/9777709

 


免責聲明!

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



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