当前位置 : 首页 » 博文聚焦 » 正文

繁简转换OpenCC,autogb 和 autob5,iconv,python的jianfan包

分类 : 博文聚焦 | 发布时间 : 2015-07-26 04:01:00 | 浏览 : 0

OpenCC

OpenCC 是跨平台、多语言的开放中文转换库,除了基本的简繁转换功能外,用户还可以选择对不同用词习惯和异体字的处理方式。

OpenCC 还提供方便的网页转换界面

OpenOffice.Org的转换功能

OpenOffice.Org提供简繁功能,使用很方便(在工具->语言->中文简繁转换)。

Google翻译功能

Google翻译也可以做简繁转换,效果分析见后面。

使用cconv转换

cconv建立在iconv之上,增加了词语转换能力,效果分析见后面。

Ubuntu用户可以用命令sudo apt-get install cconv安装。

使用cconv进行简繁转换的方法为:

cconv -f UTF8-CN -t UTF8-HK jian.txt -o fan.txt

使用iconv转换

iconv是用来转换编码的小工具。现在的iconv在执行编码从gb2312到big5的转化时,实现了简繁转换。

使用iconv进行简繁转换的方法为:

iconv -f gb2312 -t big5 gb_input.txt > big5_output.txt

如果原来的文件是UTF-8编码的,则需要使用命令:

iconv -f utf8 -t gb2312 jian.txt | iconv -f gb2312 -t big5 | iconv -f big5 -t utf8 > fan.txt

注意一定要先转化成gb2312,再由gb2312转成big5。

繁简转换则类似:

iconv -f utf8 -t big5 fan.txt | iconv -f big5 -t gb2312 | iconv -f gb2312 -t utf8 > jian.txt

如果有zh-autoconvert,则可以用它代替中间的iconv,如

iconv -f utf8 -t big5 fan.txt | autogb | iconv -f gbk -t utf8 > jian.txt

iconv -f utf8 -t gbk jian.txt | autob5 | iconv -f big5 -t utf8 > fan.txt

不同方法比较

Note.gif
注意:
由于此处涉及简繁对比,请确保在左侧语言处选择“不转换”。

测试样例

为了方便比较,选取下面一段话做测试:

中华人民共和国是工人阶级领导的、以工农联盟为基础的人民民主专政的社会主义国家。
干活 干杯  西太后   后天

正确的转换结果是:

中華人民共和國是工人階級領導的、以工農聯盟為基礎的人民民主專政的社會主義國家。
幹活 乾杯  西太后   後天

测试样例中第一句话很普通,用来检测能否完成转换的基本功能;第二行“干活”与“干杯”两个词的“干”对应的繁体字不一样,这可以检测程序是否进行了语义分析;“西太后”的“后”简繁相同,同样用于检测简繁转换的准确性。

另外,第二句话中有空格若干,用来判断转换程序是否能保留原格式。

测试结果

OpenCC

中華人民共和國是工人階級領導的、以工農聯盟爲基礎的人民民主專政的社會主義國家。
幹活 乾杯  西太后   後天

OpenOffice.Org

中華人民共和國是工人階級領導的、以工農聯盟為基礎的人民民主專政的社會主義國家。
干活 干杯  西太后   后天

Google翻译

中華人民共和國是工人階級領導的、以工農聯盟為基礎的人民民主專政的社會主義國家。
幹活乾杯西太后後天

iconv

中華人民共和國是工人階級領導的、以工農聯盟為基礎的人民民主專政的社會主義國家。
幹活 幹杯  西太後   後天

cconv

中華人民共和國是工人階級領導的、以工農聯盟為基礎的人民民主專政的社會主義國家。
幹活 乾杯  西太后   後天

不难发现,对于多解的字,OpenOffice.Org未转换,iconv按单一规则转换,而cconvOpenCC和Google翻译则能正确转换。

但是Google翻译未能保持原格式,而OpenOffice.Org、iconvcconv则很好地保留了原格式。

另外,iconv不能处理混合编码的文件。

使用cconv转换20M含部分乱码的文本文件耗时仅数秒,且效果非常理想,不会像iconv一样遇到“ә”等非常规字符或乱码字符时报错停止转换。(推荐使用)

 

偶然需要把一些繁体字的帮助页面转换成简体字的,网上搜索啦下,还真找到一个好用的工具:zh-autoconvert ,在zh-autoconvert [Debian 包介绍]有它的介绍,这个工具是Debian中文用户于广辉先生写的自动中文辨识转码程序包,提供两个应用程序autogb 和 autob5,在Debian下很好用apt-get install zh-autoconvert 就可以安装好。两个工具使用方法也很简单
标准的命令行为
 autogb/autob5 [选项] <输入流 >输出流
   选项有
    -i 输入流的编码
    --input 输入流的编码

    -o 输出流的编码
    --output 输出流的编码

这样就可以同时处理繁简体和编码问题啦。
此外 可选的编码有 gb, big5, hz, uni, utf7 或者 utf8

实际上一般简单使用可以采用如下的方法
  autogb < 输入流(文件)   >输出流(文件)
        把输入流中的繁体字转换成简体字

  autob5 < 输入流(文件)   >输出流(文件)
        把输入流中的简体字转换成繁体字

不过这个转换仅仅是字的转换,对于原来繁简体字中存在的多对一的情况没有特别处理,都是选用的常用字,所以一般繁转简问题不大,简转繁可能存在生造词(别字)情况,这点要注意。

另外找到了一个windows下的工具ConvertZ这个工具可以实现比较丰富的转换,特别还能定制一些字词的转换对应关系,也算是很方便的工具啦。

 

其实说到编码转换,那就不得不说到iconv这个库了,如果已经安装了这个工具,那在命令行下直接打这个命令就行了。下面就用这个工具来实现中文系统下的常用编码转换。

首先,来了解一下iconv这个命令的使用方法。命令格式如下

iconv -f 编码 -t 编码 文件名

-f 参数指所要转换文件的文件编码,当然必须事先知道文件的编码,不然不能正确转换。

-t 参数指希望转换成的文件编码,当然应该知道所指定文件的编码能不能转换成该编码,不然转换后的结果可能一无所用。比如你将中文编码转换成西欧的某种编码的话,是没有什么意义的。

文件名 就是你希望转换的文件的名称的,当然也可以包含路径了。

比如将a.txt文件用GB2312(简体)转换成BIG5(繁体),命令如下:

$iconv -f GB2312 -t BIG5 a.txt

当然也可以使用iconv -l来查看都有哪些编码可用,命令如下:

$iconv -l

那么,如果不知道文件的编码怎么办?比如我的系统中有繁体字编码的文件,也有UTF-8编码的文件,又有简体字编码的文件,但是系统说使用的编码是简体的。怎样把所有文件的编码都转换成简体字,或者怎样将所有文件的编码变成繁体字编码,或者怎样将所有的文件都转换成UTF-8编码呢?下面的这段程序将告诉你去怎样实现这个功能。

#!/bin/bash

#文件名
fname=$1
#临时文件,用来保存转换的结果
tmpfile="cc`date +%0H%0M%0S`.liu"
#没有输入文件名
if [ -z ${fname} ] ; then
echo "Bad file name. ";
exit;
fi
#输入的文件不存在
if [ ! -f ${fname} ] ; then
echo "File is not existed.FILE="${fname};
exit;
fi
################################################
# f_code:现有文件的编码,当不太清楚现有文件的编码的时候,
# 可以同时指定的几种可能的编码
# t_code:希望转换成的目标编码
################################################
#比如要将GB2312或者UTF-8的文件转换成BIG5(繁体)文件
t_code="BIG5" #目标编码
f_code="GB2312 UTF-8" #可以转换的文字编码

#判断系统文字编码是否为GB2312,是的话则将BIG5或者UTF-8编码的文件转换成系统一样
#的GB2312
echo $LANG | grep -i GB2312> /dev/null
if [ $? -eq 0 ] ; then
t_code="GB2312" #目标编码
f_code="BIG5 UTF-8" #可以转换的文字编码
fi

#判断系统文字编码是否为BIG5, 是的话则将GB2312或者UTF-8编码的文件转换成系统一样
#的GB2312
echo $LANG | grep -i BIG5 > /dev/null
if [ $? -eq 0 ] ; then
t_code="BIG5" #目标编码
f_code="GB2312 UTF-8" #可以转换的文字编码
fi
#如果要把GB2312,BIG5文字编码的文件统一转换成UTF-8,则应该这样
t_code="UTF-8" #目标编码
f_code="GB2312 BIG5" #可以转换的文字编码

#当然你也可以任意设置你需要互相转换的编码,但主意要保证编码之间可以自由转换。比如
#你要将GB2312转换成某种西欧编码,则没有什么意义了。
normal_msg=""
error_msg=""
#依次尝试从可以转换的文字编码开始对文件进行编码转换
for code in ${f_code} ; do
#文字编码转换
iconv -f $code -t $t_code ${fname} > ${tmpfile}
#转换成功,一旦转换成功则不用再尝试用其他编码来读取文件
if [ $? -eq 0 ] ; then
normal_msg="ICONV SUCCESSED! FILENAME=${fname} F_CODE=$code,T_CODE=$t_code"
break
else #转换失败
if [ ! -z "${error_msg}" ] ; then
error_msg="${error_msg} "
fi
error_msg="${error_msg}ICONV FAILED! FILENAME=${fname} F_CODE=$code,T_CODE=$t_code"
fi
done
#输出转换结果消息
#转换成功,则输出转换成功消息;所有尝试转换都失败的时候,则输出所有转换失败消息
if [ -z "${normal_msg}" ] ; then
echo -e ${error_msg}
else
cp -f ${tmpfile} $fname
echo ${normal_msg}
fi

#删除临时文件
if [ -f ${tmpfile} ] ; then
rm -f ${tmpfile};
fi

在上面的程序中,实际上只是实现了一个文件的转换,如果要实现多个文件的转换的话,该怎么办了,其实很简单了,只需要遍历一下文件就行了。遍历文件的方法很多,也就不详细解说了,下面仅举一个用find命令来查找文件并对找到的文件进行编码转换。命令很简单,如下:

$find . -type f -name ‘*.txt’ | xargs -l sh cc.sh

其中cc.sh是上面的程序文件。该命令查找当前目录下所有的后缀为txt的文件比对其进行编码转换。

在上面的程序中,为了说明方便,文件编码和转换的目标编码都是在程序里设定的,如果需要更加实用一点的话,可以把原文件的编码和转换的目标编码都作为参数来输入,这样的话,这个程序就不光是中文系统下的文件编码转换了,日文,韩文等等编码的转换也能很轻松实现了。
    首先发个牢骚吧,简繁转换的问题让我在网上搜了好久都没有好的答案,得到的回答尽是让我建个简繁体字的对照表然后自己查表。我就不信了,这都什么年代了,这么常规的功能还要自己造轮子。果然工夫不负苦心人,轮子终于让我找到了,名叫opencc,ibus-pinyin里的繁体部分使用了它,项目主页地址:
    http://code.google.com/p/opencc/
    不过opencc没有一个简单的教程挺让我抓狂,自己看它的源代码才搞清楚怎么弄,为造福各位和我一样为简繁转换苦恼了很久的童鞋,本人献上这篇文章,欢迎转载,转载请注明作者RunningOn。
    在献上教程之前,提醒下面两类童鞋可以不用看本文:
    1. 写Windows程序的人。Windows自己提供了LCMapString API可以做简繁转换,搜它就行了,网上例程也多。
    2. 用python的人。python下我使用过两个包,一个是jianfan,简单直观,但有bug,有些常用的字都不能转换,推荐度一般。另外一个是opencc的python绑定,主页在http://pypi.python.org/pypi/opencc-python/,网页下方有win和linux的安装包,而且网页里有教程。看不懂英文?我了个擦,那网页里面才几个单词......

python的jianfan包

Linux下用C语言如何进行简繁转换。以Ubuntu 11.10为例吧,其它发行版应该大同小异。你还需要知道一些文字编码的基础知识。
    关于编码的知识这里不打算详细介绍,但你需要知道:中文中常用的编码有gb2312, gbk, gb18030, big5, utf8和unicode。严格来讲gb18030和utf8只是unicode的编码方式,但本文中简单起见把它们认为是不同的编码,想搞清楚编码关系的自己去搜吧,资料很多。
    gb2312只含简体字,big5只含繁体字,其它几种编码都同时有简体和繁体字,gb2312可以简单认为是gbk的简体子集。一般来讲简繁转换同时包含了编码的转换,比如香港地区普遍使用big5编码,转为简体字就要先转化为gbk, gb18030, utf8编码中的一种再将繁体转化为简体。
    opencc只是一个简繁转换的库,要转换编码我们还需要一个有名的库iconv。这两库的安装方法:
    sudo apt-get install libiconv-hook-dev libopencc-dev
    libopencc-dev没有提供rpm的包,也没有提供只含库的源码,所以最方便的还是apt-get。
    iconv的教程还是有不少的,这里就不做太多介绍了。但注意不是所有编码都能自由转换的,比如如果你是想把big5直接转为gb2312是不行的。
    简繁转换的通用思路是先将编码转换为utf8,再在utf8下进行简繁转换,再将utf8转为想要的编码(如果需要)。不多说,直接上代码,该解释的都写到注释里了:
#include <iconv.h>
#include <opencc/opencc.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>

///使用iconv库将字符串从编码from_charset转换到to_charset,输入是inbuf,输出是outbuf
void m_iconv(const char *from_charset, const char * to_charset,
        const char *inbuf, size_t inlen, char *outbuf, size_t outlen)
{
    memset(outbuf,0,outlen);
    iconv_t cd;
    cd = iconv_open(to_charset,from_charset);
    if (cd==0) return;
    iconv(cd, (char **)&inbuf, &inlen, &outbuf, &outlen);
    iconv_close(cd);
}

///繁体转化为简体,编码从src_charset转换为dest_charset,输入是src,输出是dest
void cht2chs(const char* src_charset, const char * dest_charset,
    const char *src, char *dest)
{
    char utf8[1000], tempout[1000], *raw=(char *)src;
    m_iconv(src_charset, "utf8", raw, strlen(raw), utf8, sizeof(utf8));    //先转为utf8
    opencc_t od = opencc_open(OPENCC_DEFAULT_CONFIG_TRAD_TO_SIMP);
    char * chsutf8 = opencc_convert_utf8(od, utf8, strlen(utf8));    //简繁转换
    strcpy(tempout, chsutf8);
    free(chsutf8);    //一定要free不然会内存泄漏
    opencc_close(od);
    size_t len = strlen(tempout);
    m_iconv("utf8", dest_charset, tempout, len, dest, len*2+1);    //再转到目标编码
}

///简体转化为繁体,编码从src_charset转换为dest_charset,输入是src,输出是dest
void chs2cht(const char* src_charset, const char * dest_charset,
    const char *src, char *dest)
{
    char utf8[1000], tempout[1000], *raw=(char *)src;
    m_iconv(src_charset, "utf8", raw, strlen(raw), utf8, sizeof(utf8));    //先转为utf8
    opencc_t od = opencc_open(OPENCC_DEFAULT_CONFIG_SIMP_TO_TRAD);
    char * chsutf8 = opencc_convert_utf8(od, utf8, strlen(utf8));    //简繁转换
    strcpy(tempout, chsutf8);
    free(chsutf8);    //一定要free不然会内存泄漏
    opencc_close(od);
    size_t len = strlen(tempout);
    m_iconv("utf8", dest_charset, tempout, len, dest, len*2+1);    //再转到目标编码
}

int main()    //main里放测试代码
{
    char src[] = "\264\372\270\325", dest[100];    //big5编码的繁体的"测试"
    cht2chs("big5", "utf8", src, dest);    //根据实际情况,把"utf8"改为你的locale
    printf("%s\n", dest);    //输出"测试"
    return 0;
}

将以上代码保存到test.c,可以根据实际情况将main函数第二行的utf8改为你的locale。
编译方法:
    gcc -o test test.c -lopencc -liconv_hook
运行:
    ./test
    然后就可以看到输出两个简体字"测试"。
    把m_iconv, cht2chs和chs2cht这三个函数复制到你的代码里就可以直接使用了。

    最后再说明一下,opencc算是所有简繁转换库中做得很不错的了,能处理异体字,还能对一简对多繁和一繁对多简的情况自动处理。之前有一个简繁转换的cconv项目就做得不太好,而且它用GPL协议,对开发者限制太多。而opencc使用Apache开源协议,很宽松。opencc项目很赞,可惜作者在教程上没花什么功夫,所以很长时间都没有在网上看到谁使用它。如果opencc作者看到此文请写个官方的教程吧,或者把本文直接链过去:)

 

相关阅读: