研究了在網上能找到的自動識別字符集的辦法,有效的就是利用第三方類庫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