ICU

使用ICU进行字符集探测
文档译稿
原文http://userguide.icu-project.org/conversion/detection

Character Set Detection 字符集探测
Overview 概述
字符集探测是对未知格式的字符数据进行确定字符集或者编码的过程。这充其量是一个使用统计学和启发式方法进行的一项不精确的操作。也正因如此,如果可以提供一种语言的至少几百个字节的字符数据,那么探测将取得最好的效果。在某些情况下,语言的种类也能同编码一同探测出来。
字符集探测有几种不同的技术。对于多字节的字符编码,字节的顺序需要按照一定的模式进行验证。被检测过的字符也要使用在那种编码中出现频率比较高的一些字符进行验证。对于单字节编码,需要对每种可以用那种编码书写的语言中的一些最常出现的三个字母组(three letter groups)进行验证。
输入可以是Java输入流,也可以是一个字节数组。探测的输出是一个可能的字符集列表,最可能的字符集排在最前。简单点,你可以使用Java Reader按照探测出来的字符集读取数据。
CharsetMatch
CharsetMatch保存着比较输入数据和一个特定的编码的结果。你可使用这个类的实例来获取字符集的名称,语言种类,匹配的精准度。你也使用这个类来解码输入数据。
为了看看匹配的效果如何,可以使用getConfidence()方法获取一个精确度的值。这是一个0-100的整型,越大说明匹配的把握越大。
CharsetMatch match = ...;
int confidence;

confidence = match.getConfidence();

if (confidence < 50 ) {
// handle a poor match...
} else {
// handle a good match...
}
C语言中可以使用ucsdet_getConfidence(const UCharsetMatch *ucsm, UErrorCode *status)来获取精确度
const UCharsetMatch *ucm;
UErrorCode status = U_ZERO_ERROR;
int32_t confidence = ucsdet_getConfidence(ucm, &status);
if (confidence <50 ){
//handle a poor match...
} else {
//handle a good match...
}
获取字符集(可以在Java中作为encoding name)的名字,可以使用getName()方法。
CharsetMatch match = ...;
byte characterData[] = ...;
String charsetName;
String unicodeData;
charsetName = match.getName();
unicodeData = new String(characterData, charsetName);
使用C语言可以这样:
const UCharsetMatch *ucm;
UErrorCode status = U_ZERO_ERROR;
const char *name = ucsdet_getName(ucm, &status);
可使用getLanguage()方法获取被探测语言的三个字母的ISO代码(three letter ISO code)。若是不能确定语言种类,那么将返回null。
CharsetMatch match = ...;
String languageCode;
languageCode = match.geLanguae();
if (languageCode != null) {
// handle the language code...
}

在C语言中可以使用ucsdet_getLanguage(const UCharsetMatch *ucsm, UErrorCode *status)函数来获取语言代码。若是不能确定语言种类,函数会返回一个空字符串。
const UCharsetMatch *ucm;
UErrorCode status = U_ZERO_ERROR;
const char *language = ucsdet_getLanguage(ucm, &status);
可以使用getString()方法获取包含被转化过的数据的一个Java String。
public static void get(){
CharsetMatch match = ...;
String unicodeData;
unicodeData = match.getString();
如果想要限制字符串中的字符书,可以传递一个最大值给getString().
CharsetMatch match = ...;
Reader reader;
StringBuffer sb = new StringBuffer();
char[] buffer = new char[1024];
int bytesRead = 0;

reader = match.getReader();

while ((bytesRead = reader.read(buffer, 0, 1024)) >= 0) {
sb.append(buffer, 0, bytesRead);
}
reader.close();
CharsetDetector
CharsetDetector类用来进行探测工作。它参照所有的字符集对输入数据进行匹配,计算出一个保存结果的CharsetMatch对象列表。输入可以是byte array,也可以是java.io.InputStream
使用CharsetDetector,第一步需要创建CharsetDetector对象,然后使用setText()设置input data。因为设置输入数据和构造函数是分开的,可以方便的重 CharsetDetector对象。
CharsetDetector detector;
byte[] byteData = ...;
InputStream streamData = ...;

detector = new CharsetDetector();

detector.setText(byteData);
// use detector with byte data...

detector.setText(streamData);
// use detector with stream data...
想知道哪个字符集和你输入的数据最匹配,可以使用detect()方法。Detect()返回一个最匹配的字符集对应的CharsetMathc对象。
CharsetDetector detector;
CharsetMatch match;
byte[] byteData = ...;
detector = new CharsetDetector();
detector.setText(byteData);
match = detector.detect();
C语言中,可以使用ucsdet_detect( UCharsetDetector *csd , UErrorCode *status)函数来获取与输入数据最匹配的字符集。
UCharsetDetector* csd;
const UCharsetMatch *ucm;
static char buffer[BUFFER_SIZE] = {....};
int32_t inputLength = ... //length of the input text
UErrorCode status = U_ZERO_ERROR;
ucsdet_setText(csd, buffer, inputLength, &status);
ucm = ucsdet_detect(csd, &status);
如果想要知道所有与输入数据匹配精确度大于0的字符集集合,可以使用detectAll()方法。此方法返回一个CharsetMatch数组,里面的数据已经按照精确度由高到低进行了排序。
CharsetDetector detector;
CharsetMatch matches[];
byte[] byteData = ...;

detector = new CharsetDetector();

detector.setText(byteData);
matches = detector.detectAll();

for (int m = 0; m < matches.length; m += 1) {
// process this match...
}
注意:ucsdet_detectALL函数可以用来在C语言中探测所有的字符集可能。matchesFound是一个指针指针,他指向一个保存输入数据对应的字符集列表的变量。
CharsetDetector类也实现了一个比较粗糙的输入过滤器,用来去除html、xml标签。这个过滤器在创建CharsetDetector的时候默认是关闭的,如果想开启它,需要调用enableInputFilter()方法。此方法需要一个boolean型参数。传递true开启过滤,false关闭过滤。
CharsetDetector detector;
CharsetMatch match;
byte[] byteDataWithTags = ...;

detector = new CharsetDetector();

detector.setText(byteDataWithTags);
detector.enableInputFilter(true);
match = detector.detect();
C中可以使用ucsdet_enableInputFilter( UCharsetDetector* csd, UBool filter)函数开启过滤器
UCharsetDetector* csd;
const UCharsetMatch *ucm;
static char buffer[BUFFER_SIZE] = {....};
int32_t inputLength = ... //length of the input text
UErrorCode status = U_ZERO_ERROR;
ucsdet_setText(csd, buffer, inputLength, &status);
ucsdet_enableInputFilter( csd, TRUE);
ucm = ucsdet_detect(csd, &status);
如果你知道结构化的输入数据的更多的细节,最后在使用CharsetDetetor之前自己先过滤一下。例如,你可能知道数据源于包含CSS样式的HTML页面,而CSS将不会被滤波器过滤掉。(这可能就要先自己处理一下了,译者)
可以使用inputFilterEnabled()检查输入过滤器是否开启。
CharsetDetector detector;
detector = new CharsetDetector();

// do a bunch of stuff with detector
// which may or may not enable the input filter...

if (detector.inputFilterEnabled()) {
// handle enabled input filter
} else {
// handle disabled input filter
}
注意:ICU4C API提供了uscdet_isInputFilterEnabled(const UCharsetDetector* csd)函数检查过滤器是否开启。
CharsetDetector类提供了两个比较便捷的方法,可以将探测和转换数据一步完成:getReader()和getString()方法。
CharsetDetector detector;
byte[] byteData = ...;
InputStream streamData = ...;
String unicodeData;
Reader unicodeReader;

detector = new CharsetDetector();

unicodeData = detector.getString(byteData, null);

unicodeReader = detector.getReader(streamData, null);
注意:getReader()和getString()的第二个参数是declaredEncoding,此参数目前没有使用。还有一个setDeclaredEncoding()方法,目前也没有使用。
下面的代码与上面的便捷方法等效:
CharsetDetector detector;
CharsetMatch match;
byte[] byteData = ...;
InputStream streamData = ...;
String unicodeData;
Reader unicodeReader;

detector = new CharsetDetector();

detector.setText(byteData);
match = detector.detect();
unicodeData = match.getString();

detector.setText(streamData);
match = detector.detect();
unicodeReader = match.getReader();


Detected Encodings
下表展示了所有能被探测的字符集。可以用getAllDetectableCharsets()获取这个列表,但是不能获取语言种类。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/telnetor/archive/2010/02/06/5555349.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值