断定文件编码或文本流编码的方法
在程序中,文本文件常常用来存储标准的ASCII码文本,好比英文、加减乘除等号这些运算符号。文本文件也可能用于存储一些其余非ASCII字符,如基于GBK的简体中文,基于GIG5的繁体中文等等。在存储这些字符时须要正确指定文件的编码格式;而在读取这些文本文件时,有时候就须要自动断定文件的编码格式。
按照给定的字符集存储文本文件时,在文件的最开头的三个字节中就有可能存储着编码信息,因此,基本的原理就是只要读出文件前三个字节,断定这些字节的值,就能够得知其编码的格式。其实,若是项目运行的平台就是中文操做系统,若是这些文本文件在项目内产生,即开发人员能够控制文本的编码格式,只要断定两种常见的编码就能够了:GBK和UTF-8。因为中文Windows默认的编码是GBK,因此通常只要断定UTF-8编码格式。
对于UTF-8编码格式的文本文件,其前3个字节的值就是-1七、-6九、-65,因此,断定是不是UTF-8编码格式的代码片断以下:
- java.io.File f=new java.io.File("待断定的文本文件名");
- try{
- java.io.InputStream ios=new java.io.FileInputStream(f);
- byte[] b=new byte[3];
- ios.read(b);
- ios.close();
- if(b[0]==-17&&b[1]==-69&&b[2]==-65)
- System.out.println(f.getName()+"编码为UTF-8");
- else System.out.println(f.getName()+"多是GBK");
- }catch(Exception e){
- e.printStackTrace();
- }
上述代码只是简单断定了是不是UTF-8格式编码的文本文件,若是项目对要断定的文本文件编码不可控(好比用户上传的一些HTML、XML等文本),能够采用一个现成的开源项目:cpdetector,它所在的网址是:
http://cpdetector.sourceforge.net/
。它的类库很小,只有500K左右,利用该类库断定文本文件的代码以下:
- /*------------------------------------------------------------------------
- detector是探测器,它把探测任务交给具体的探测实现类的实例完成。
- cpDetector内置了一些经常使用的探测实现类,这些探测实现类的实例能够经过add方法
- 加进来,如ParsingDetector、 JChardetFacade、ASCIIDetector、UnicodeDetector。
- detector按照“谁最早返回非空的探测结果,就以该结果为准”的原则返回探测到的
- 字符集编码。
- --------------------------------------------------------------------------*/
- cpdetector.io.CodepageDetectorProxy detector =
- cpdetector.io.CodepageDetectorProxy.getInstance();
- /*-------------------------------------------------------------------------
- ParsingDetector可用于检查HTML、XML等文件或字符流的编码,构造方法中的参数用于
- 指示是否显示探测过程的详细信息,为false不显示。
- ---------------------------------------------------------------------------*/
- detector.add(new cpdetector.io.ParsingDetector(false));
- /*--------------------------------------------------------------------------
- JChardetFacade封装了由Mozilla组织提供的JChardet,它能够完成大多数文件的编码
- 测定。因此,通常有了这个探测器就可知足大多数项目的要求,若是你还不放心,能够
- 再多加几个探测器,好比下面的ASCIIDetector、UnicodeDetector等。
- ---------------------------------------------------------------------------*/
- detector.add(cpdetector.io.JChardetFacade.getInstance());
- //ASCIIDetector用于ASCII编码测定
- detector.add(cpdetector.io.ASCIIDetector.getInstance());
- //UnicodeDetector用于Unicode家族编码的测定
- detector.add(cpdetector.io.UnicodeDetector.getInstance());
- java.nio.charset.Charset charset = null;
- File f=new File("待测的文本文件名");
- try {
- charset = detector.detectCodepage(f.toURL());
- } catch (Exception ex) {ex.printStackTrace();}
- if(charset!=null){
- System.out.println(f.getName()+"编码是:"+charset.name());
- }else
- System.out.println(f.getName()+"未知");
上面代码中的detector不只能够用于探测文件的编码,也能够探测任意输入的文本流的编码,方法是调用其重载形式:
- charset=detector.detectCodepage(待测的文本输入流,测量该流所需的读入字节数);
上面的字节数由程序员指定,字节数越多,断定越准确,固然时间也花得越长。要注意,字节数的指定不能超过文本流的最大长度。
断定文件编码的具体应用举例:
属性文件(.properties)是Java程序中的经常使用文本存储方式,象STRUTS框架就是利用属性文件存储程序中的字符串资源。它的内容以下所示:
读入属性文件的通常方法是:
- FileInputStream ios=new FileInputStream("属性文件名");
- Properties prop=new Properties();
- prop.load(ios);
- ios.close();
利用java.io.Properties的load方法读入属性文件虽然方便,但若是属性文件中有中文,在读入以后就会发现出现乱码现象。发生这个缘由是load方法使用字节流读入文本,在读入后须要将字节流编码成为字符串,而它使用的编码是“iso-8859-1”,这个字符集是ASCII码字符集,不支持中文编码,因此这时须要使用显式的转码:
- String value=prop.getProperty("属性名");
- String encValue=new String(value.getBytes("iso-8859-1"),"属性文件的实际编码");
在上面的代码中,属性文件的实际编码就能够利用上面的方法得到。固然,象这种属性文件是项目内部的,咱们能够控制属性文件的编码格式,好比约定采用Windows内定的GBK,就直接利用"gbk"来转码,若是约定采用UTF-8,也能够是使用"UTF-8"直接转码。若是想灵活一些,作到自动探测编码,就可利用上面介绍的方法测定属性文件的编码,从而方便开发人员的工做。
欢迎关注本站公众号,获取更多信息