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

时间: 2024-10-21 13:03:12

利用java.nio.charset.CharsetDecoder自动识别字符集的相关文章

我的Java开发学习之旅------>Java NIO 报java.nio.charset.MalformedInputException: Input length = 1异常

今天在使用Java NIO的Channel和Buffer进行文件操作时候,报了java.nio.charset.MalformedInputException: Input length = 1异常,具体如下: java.nio.charset.MalformedInputException: Input length = 1 at java.nio.charset.CoderResult.throwException(CoderResult.java:260) at java.nio.char

scala文件读取报错“java.nio.charset.MalformedInputException: Input length = 1”

今天写spark程序的时候遇到了一个问题就是,读取文件的时候报了一个错:"Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1" 读取文件的代码如下: 一看这个这个错"nio"错误,第一感觉就是读文件方法这里出了问题,于是点击去看了一下Source.fromFile这个方法的源码: 果然,这个方法的重载有好几个,但是每一都直接或间

springcloud采坑--Zuul上传文件报java.nio.charset.IllegalCharsetNameException: UTF-8;boundary=sqgzzmMxl1UPdIp0IAYnQgUIAr9yNewVAzKIX

报错日志: 2018-12-17 10:01:19,688 ERROR [io.undertow.request] (default task-3) UT005023: Exception handling request to /xxx/app/bannerMaterialManager/uploadBannerSysGoodsPicture: java.nio.charset.IllegalCharsetNameException: UTF-8;boundary=sqgzzmMxl1UPdI

Jython 在 Eclipse 控制台报错 console: Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0.

在 Eclipse 中使用 Jython 时报错 解决办法 右键 --> Run As --> Run Configurations --> Arguments --> 设置 VM arguments Jython 在 Eclipse 控制台报错 console: Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0. 原文地址:https://www.cnblogs.com/0820LL/p

java.nio.charset.MalformedInputException: Input le

[ERROR - org.apache.flume.source.SpoolDirectorySource$SpoolDirectoryRunnable.run(SpoolDirectorySource.java:256)] FATAL: Spool Directory source source1: { spoolDir: /flume/log/ }: Uncaught exception in SpoolDirectorySource thread. Restart or reconfigu

JAVA NIO学习记录1-buffer和channel

什么是NIO? Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java IO API.NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的.基于通道的IO操作.NIO将以更加高效的方式进行文件的读写操作. Java NIO 与IO 的主要区别 Java NIO系统的核心在于:通道(Channel)和缓冲区(Buffer).通道表示打开到IO 设备(例如:文件.套接字)的连接.若需要使用NIO 系统,需要获取用

JAVA NIO 服务器与客户端实现示例

以下代码只兼容Java 7及以上版本,对于一些关键地方请看注释说明. 公共类: package com.stevex.app.nio; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; imp

Java NIO、NIO.2学习笔记

相关学习资料 http://www.molotang.com/articles/903.html http://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html 目录 1. NIO.NIO.2简介 2. NIO中的关键技术 1. NIO.NIO.2简介 Java中的输入流.输出流都是阻塞式的输入.输出.不仅如此,传统的输入流.输出流都是通过字节的移动来处理的(即使是字符流,在底层也是通过字节流来进行处理的),也就是说,面向

Java NIO与IO的差别和比較

导读 J2SE1.4以上版本号中公布了全新的I/O类库.本文将通过一些实例来简介NIO库提供的一些新特性:非堵塞I/O,字符转换,缓冲以及通道. 一. 介绍NIO NIO包(java.nio.*)引入了四个关键的抽象数据类型,它们共同解决传统的I/O类中的一些问题. 1. Buffer:它是包括数据且用于读写的线形表结构.当中还提供了一个特殊类用于内存映射文件的I/O操作. 2. Charset:它提供Unicode字符串影射到字节序列以及逆影射的操作. 3. Channels:包括socket