• 利用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

  • 相关阅读:
    转:裸接口防护,避免恶意盗刷和爬取
    oracle = : := 和变量绑定 oracle通配符和运算符
    169.254地址无网关信息 ----- 解决方案 启动DHCP服务
    NAS DAS SAN 磁带机 tco
    linux 权限详解
    转载:哈希加密算法 MD5,SHA-1,SHA-2,SHA-256,SHA-512,SHA-3,RIPEMD-160
    MD5,SHA1 都是哈希 摘要算法 MD5+SALT BCRYPT
    iOS开发JSON字符串和字典互转
    iOS开发线程之NSThread
    iOS开发NSMutableArray数组越界处理
  • 原文地址:https://www.cnblogs.com/lngrvr/p/java_AutoCharsetReader.html
Copyright © 2020-2023  润新知