自动检测文本的字符集
(Java port of Mozilla charset detector 工具的使用方法)

 

Java port of Mozilla charset detector是Mozilla组织开发的用于浏览器自动识别网页字符集的工具的一个JAVA实现。Mozilla有关该工具的地址是:http://www.mozilla.org/projects/intl/chardet.html
本JAVA实现版本的地址是:http://sourceforge.net/projects/jchardet/
在JAVA系统开发中,经常遇到字符集的问题(其实不是JAVA的问题,而是软件行业的历史遗留问题),在时候不知道文本内容的编码方式,在处理的时候出现一些意想不到的问题,通过使用此工具,虽不能百分百准确检测字符集,但还可将就用用。此工具检测效率不是很高,使用后对系统性能会有一点影响,对性能要求很高的系统谨慎使用。

下面是如何使用此工具的一个简单说明:

第一步:
在需要检测字符集的类实现接口nsICharsetDetectionObserver,需要实现其中的一个方法:Notify()。该方法会在检测结束的时候被调用并返回检测的字符集(不论对错)。

接口代码如下:

package org.mozilla.intl.chardet ;

import java.lang.* ;

public interface nsICharsetDetectionObserver {
  public void Notify(String charset) ;
}

 

第二步:
初始化nsDetector类,然后对字符串流进行检测,如果检测到有非ASCII的字符,则调用nsDetector的DoIt()方法进行检测。

第三步:
当字符串流处理结果后,调用nsDetector的DataEnd()方法,检测引擎会向调用者返回检测到的字符集。下面是一个调用该工具检测指定URL的页面编码方式的例子:

 

package org.mozilla.intl.chardet ;
import java.io.* ;
import java.net.* ;
import java.util.* ;
import org.mozilla.intl.chardet.* ;

public class HtmlCharsetDetector {

    public static boolean found = false ;

    public static void main(String argv[]) throws Exception {

	if (argv.length != 1 && argv.length != 2) {

	  System.out.println("Usage: HtmlCharsetDetector <url> [<languageHint>]");

	  System.out.println("");
	  System.out.println("Where <url> is http://...");
	  System.out.println("For optional <languageHint>. Use following...");
	  System.out.println("		1 => Japanese");
	  System.out.println("		2 => Chinese");
	  System.out.println("		3 => Simplified Chinese");
	  System.out.println("		4 => Traditional Chinese");
	  System.out.println("		5 => Korean");
	  System.out.println("		6 => Dont know (default)");

	  return ;
	} 


	//初始化nsDetector() ;
	int lang = (argv.length == 2)? Integer.parseInt(argv[1]) : nsPSMDetector.ALL ;
	nsDetector det = new nsDetector(lang) ;

	//设置观察者...
	//如果检测出了字符集,则会调用Notify()方法.

	det.Init(new nsICharsetDetectionObserver() {
		public void Notify(String charset) {
		    HtmlCharsetDetector.found = true ;
		    System.out.println("CHARSET = " + charset);
		}
    	});

	URL url = new URL(argv[0]);
	BufferedInputStream imp = new BufferedInputStream(url.openStream());
	
	byte[] buf = new byte[1024] ;
	int len;
	boolean done = false ;
	boolean isAscii = true ;
	   
	while( (len=imp.read(buf,0,buf.length)) != -1) {

		//检测字符串流中是否只包含ASCII
		if (isAscii)
		    isAscii = det.isAscii(buf,len);

                //如果包含非ASCII字符,则调用DoIt()方法进行检测
		if (!isAscii && !done)
 		    done = det.DoIt(buf,len, false);
	}
	det.DataEnd();

	if (isAscii) {
	   System.out.println("CHARSET = ASCII");
	   found = true ;
	}

	if (!found) {
	   String prob[] = det.getProbableCharsets() ;
	   for(int i=0; i<prob.length; i++) {
		System.out.println("Probable Charset = " + prob[i]);
	   }
	}
    }
}

 

 

下面是检测文本文件字符编码的例子,跟检测URL的差不多,只改了输入流获取方式:

package com.iteye.sheng.util.tools;

import java.io.* ;
import java.net.* ;
import java.util.* ;
import org.mozilla.intl.chardet.* ;

public class FileCharsetDetector {

  public static boolean found = false ;

  public static void main(String argv[]) throws Exception {

    if (argv.length != 1 && argv.length != 2) {

      System.out.println("Usage: FileCharsetDetector <file> [<languageHint>]");

      System.out.println("");
      System.out.println("Where <file> is C:/xxxxx.txt");
      System.out.println("For optional <languageHint>. Use following...");
      System.out.println("        1 => Japanese");
      System.out.println("        2 => Chinese");
      System.out.println("        3 => Simplified Chinese");
      System.out.println("        4 => Traditional Chinese");
      System.out.println("        5 => Korean");
      System.out.println("        6 => Dont know (default)");

      return ;
    }


    //初始化nsDetector() ;
    int lang = (argv.length == 2)? Integer.parseInt(argv[1]) : nsPSMDetector.ALL ;
    nsDetector det = new nsDetector(lang) ;

    //设置观察者...
    //如果检测出了字符集,则会调用Notify()方法.
    det.Init(new nsICharsetDetectionObserver() {
      public void Notify(String charset) {
        FileCharsetDetector.found = true ;
        System.out.println("CHARSET = " + charset);
      }
    });

    String filename = argv[0];
    BufferedInputStream imp = new BufferedInputStream(new FileInputStream(filename));
    
    byte[] buf = new byte[1024] ;
    int len;
    boolean done = false ;
    boolean isAscii = true ;
       
    while( (len=imp.read(buf,0,buf.length)) != -1) {

      //检测字符串流中是否只包含ASCII
      if (isAscii)
        isAscii = det.isAscii(buf,len);
      
      //如果包含非ASCII字符,则调用DoIt()方法进行检测
      if (!isAscii && !done)
        done = det.DoIt(buf,len, false);
    }
    det.DataEnd();

    if (isAscii) {
      System.out.println("CHARSET = ASCII");
      found = true ;
    }

    if (!found) {
      String prob[] = det.getProbableCharsets() ;
      for(int i=0; i<prob.length; i++) {
        System.out.println("Probable Charset = " + prob[i]);
      }
    }
  }
}