Linux下在程序中如何进行繁体中文和简体中文的转换
欢迎转载,转载请注明作者RunningOn
20111019
首先发个牢骚吧,简繁转换的问题让我在网上搜了好久都没有好的答案,得到的回答尽是让我建个简繁体字的对照表然后自己查表。我就不信了,这都什么年代了,这么常规的功能还要自己造轮子。果然工夫不负苦心人,轮子终于让我找到了,名叫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的安装包,而且网页里有教程。看不懂英文?我了个擦,那网页里面才几个单词......
本文的重点是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作者看到此文请写个官方的教程吧,或者把本文直接链过去:)