中文简繁互转的三种方法
来源:互联网 发布:淘宝如何增加排名 编辑:程序博客网 时间:2024/05/21 00:44
中文简繁互转的三种方法
(API对照表Unicode)
汉字处理是我们广大程序员所面对的中国特色问题之一,都是用汉语,干嘛非要整个简体繁体,我只能心里暗骂,该死的政治。没办法,抱怨归抱怨,问题还是要解决。本文主要是总结几种现有的中文简繁互转方法,内容大部分来自前人成果,小部分是自己的心得,在此感谢这些我不认识的朋友。
目前网络上最流行的转换方式是利用API函数,但是大部分都有或多或少的问题,如:在繁体下无法工作,未对原理进行解释等;本文除了介绍API方式外还将介绍另外两种方式。
中文编码简介
中文编码目前主要存在以下四种,GB2312,GBK,BIG5和Unicode。
GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,由国家标准总局发布,1981年5月1日实施,通行于大陆。新加坡等地也使用此编码。GB2312码收录了大部分普通的汉字,共6763字。但是对于古文和人名中出现的罕见字没有收录,而且也没有收录港台地区广泛使用的繁体字。比如,我们的朱镕基总理的“镕”就没在GB2312里,直接导致当初很多报社用“钅容”拼起来代替。正是这个缺点导致GBK的诞生。
GBK编码是中国大陆制订的、等同于UCS的新的中文编码扩展国家标准。GBK工作小组于1995年10月,同年12月完成GBK规范。该编码标准兼容GB2312,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。值得注意的是,GBK自身并非国家标准,只是曾由国家技术监督局标准化司、电子工业部科技与质量监督司公布为“技术规范指导性文件”。
Big5码的产生,是因为当时台湾不同厂商各自推出不同的编码,如IBM 5550、王安码等,彼此不能兼容;另一方面,台湾当时尚未推出官方的汉字编码,而中国内地所推行的GB 2312编码,亦未有收录繁体字。在这样的时空背景下,为了使台湾早日进入信息时代,所采行的一个计划;同时,这个计划对于以台湾为核心的亚洲汉字圈也产生了久远的影响。
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求,其中也包含了简体和繁体中文。1990年开始研发,1994年正式公布。
四种中文编码比较
编码集
中文编码方式
中文编码表
GB2312
双字节
高位:A1 – F7
低位:A1 – FE
GBK
双字节
高位:81 – FE
低位:40 – 7E 80 – FE
BIG5
双字节
高位:81 – FE
低位:40 – 7E A1 – FE
Unicode(UTF-16)
双字节
4E00 – 9FBF
API方式
API方式主要是利用三个windows 函数实现,MultiByteToWideChar,WideCharToMultiByte和LCMapString。MultiByteToWideChar和WideCharToMultiByte是用来实现Ansi和Unicode之间的转换。LCMapString是用来实现各种字符集之间转换。
由于GBK码包含了简体和繁体,API方式实现中文简繁互转实际上是利用了GBK码作为中介,先转换成GBK码再转成GB2312和BIG5码。
简体转繁体:
GB2312和GBK在简体编码上是重合的,所以没必要在转换成GBK,直接使用LCMapString来实现简繁转换。
function APIGbToBig5(valStr: string): string;
var
Len: Integer;
P: PAnsiChar;
local: LCID;
begin
Len := Length(valStr) + 1;
local := MAKELCID(
MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
SORT_CHINESE_PRCP);
P := GetMemory(Len);
try
LCMapString(local, LCMAP_TRADITIONAL_CHINESE, PAnsiChar(valStr),
Len, P, Len);
Result := P;
finally
FreeMemory(P);
end;
end;
繁体转简体:
首先将BIG5码转换成Unicode,再把Unicode转换成GBK码,最后通过LCMapString实现从简繁转换。
function APIBig5ToGB(valStr: string): string;
var
Len: Integer;
P: PAnsiChar;
local: LCID;
begin
////big5 - > gbk
valStr := GBUnicodeToAnsi(BIG5AnsiToUnicode(valStr));
local := MAKELCID(
MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
SORT_CHINESE_BIG5);
Len := Length(valStr) + 1;
P := GetMemory(Len);
try
LCMapString(local, LCMAP_SIMPLIFIED_CHINESE, PAnsiChar(valStr),
Len, P, Len);
Result := P;
finally
FreeMemory(P);
end;
end;
对照表方式
对照表方式是通过将所有的中文字符做成一张简繁字符对照表,再根据索引来查找翻译。这种方式简单实用也好理解,速度也还不错,缺点就是这么大张表可得糟蹋大概几十K内存。
这种方式看起来首要解决的问题就是这个码表如何建立,码表的建立需要解决两个问题,一个是简繁体的对应关系,第二个是中文字符到索引的映射算法。简繁体对应关系好说,根据GB2312和BIG5的编码表可以生成2张包含所有中文字的列表,再通过目前的翻译软件(如:Office自带的简繁互转,Google的在线翻译或者其他的翻译软件)实现简繁转换,这样这张表就生成了。本文的附带源码中有生成工具,实现了此过程。对于索引映射算法,也是根据码表关系生成,下面分别介绍。
简体转繁体:
索引算法:
function Hash(valStr: string): Integer;
begin
if Length(valStr) = 2 then
begin
Result := (Ord(valStr[1]) - $A1)*($FE-$A1+1) + (Ord(valStr[2]) - $A1)
end else
Result := -1;
end;
转换代码:
function AGB2BIG5(valGBString: string): string;
var
Idx, strLen: Integer;
G, B: Word;
begin
Result := '';
strLen := Length(valGBString);
Idx := 1;
while Idx <= strLen do
begin
if (valGBString[Idx] >= #$A1) and (valGBString[Idx] <= #$F7) and
(valGBString[Idx + 1] >= #$A0) and (valGBString[Idx + 1] <= #$FF) then
begin
G := Hash(valGBString[Idx] + valGBString[Idx + 1]);
if (G >= Low(CodeArray)) and (G <= High(CodeArray)) then
B := CodeArray[G]
else
B := G;
Result := Result + Chr(Hi(B)) + Chr(Lo(B));
Inc(Idx, 2);
end else
begin
Result := Result + valGBString[Idx];
Inc(Idx, 1);
end;
end;
end;
繁体转简体:
索引算法:
function Hash(valStr: string): Integer;
var
loCount, Step: Word;
begin
Step := $7F - $40;
loCount := $7F - $40 + $FF - $A1;
if Length(valStr) = 2 then
begin
if (valStr[2] >= #$40) and (valStr[2] <= #$7E) then
Result := (Ord(valStr[1]) - $A1)*loCount + (Ord(valStr[2]) - $40)
else
Result := (Ord(valStr[1]) - $A1)*loCount + Step + (Ord(valStr[2]) - $A1);
end else
Result := -1;
end;
转换代码:
function ABIG52GB(valBig5String: string): string;
var
Idx, strLen: Integer;
G, B: Word;
begin
Result := '';
strLen := Length(valBig5String);
Idx := 1;
while Idx <= strLen do
begin
if (valBig5String[Idx] >= #$A1) and (valBig5String[Idx] <= #$F9) and
(valBig5String[Idx + 1] >= #$40) and (valBig5String[Idx + 1] <= #$FE) then
begin
G := Hash(valBig5String[Idx] + valBig5String[Idx + 1]);
if (G >= Low(CodeArray)) and (G <= High(CodeArray)) then
B := CodeArray[G]
else
B := G;
Result := Result + Chr(Hi(B)) + Chr(Lo(B));
Inc(Idx, 2);
end else
begin
Result := Result + valBig5String[Idx];
Inc(Idx, 1);
end;
end;
end;
Unicode方式
Unicode编码中中文的简体繁体统一分布在一个区段中,之间也没有对应关系(实际上也不可能有)。所以这种方式的转换实际上也是通过对照表,只不过这个表的建立有所不同,在Unicode中的中文字,对于简体字和繁体字中重合的这部分字符都是对应同一个编码,所以对照表只需要包含没有重合的那部分字,这样这个表就小了很多,但是新的问题又来了,我上哪儿去弄这些不重合的字符,说实话我也没找到完整的,在维基百科上已经建立了一个项目,专门做这件事情,虽然不是100%完整,但是大部分都包含了。本文的附带源码中有生成工具生成的对照表就是这么生成的,已经能够翻译大部分常见的字符了。
简体转繁体:
function UGB2BIG5(valGBString: WideString): WideString;
var
I: Integer;
G, B: Word;
begin
Result := valGBString;
for I := 1 to Length(valGBString) do
begin
G := Word(valGBString[I]);
if (G >= GBFirst) and (G <= GBEnd) then
begin
B := CodeArray[G];
if B = 0 then
B := G;
Result[I] := WideChar(B);
end;
end;
end;
繁体转简体:
function UBIG52GB(valGBString: WideString): WideString;
var
I: Integer;
G, B: Word;
begin
Result := valGBString;
for I := 1 to Length(valGBString) do
begin
G := Word(valGBString[I]);
if (G >= BIG5First) and (G <= BIG5End) then
begin
B := CodeArray[G];
if B = 0 then
B := G;
Result[I] := WideChar(B);
end;
end;
end;
附带源码下载
源码中包含了翻译单元,演示实例和字典生成工具,实例在简体系统繁体系统下均测试通过,点击下载。
交流
以上为个人心得总结,如有不对之处欢迎指正。邮箱:heroyin@gmail.com
- 中文简繁互转的三种方法
- cocos2dx 显示中文的三种方法
- 中文三种内码转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法!
- ofstream打开中文路径的三种方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 三种常见中文内码的转换方法
- 解决Cocos2d-x中文乱码的三种方法
- Java中文件读入输出的三种方法详解
- OpenSessionInViewFilter
- 短信群发接口测试(vb+get/post)
- .net cf 3.5安装包的位置
- Hibernate的主键生成器generator在SQLServer中的使用
- QT Creator 2.0编译会将可执行文件生成到一个类似projectname_build-desktop的目录中,解决办法
- 中文简繁互转的三种方法
- Oracle 语法之 OVER (PARTITION BY ..) 及开窗函数
- ExtJs之Ext.data.Store
- 在IE6下z-index失效
- CXF之Interceptors
- 用javascript实现显示当前时间
- struts2 参数绑定和二次绑定
- asp.net 网站部署问题:
- sed 示例