简体中文和繁体中文的转换

目前,大陆地区常见的中文编码有以下三种。
GB2312
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。在windows中的代码页是CP936。
GBK
GBK最初是由微软对GB2312的扩展,也就是CP936字码表 (Code Page 936)的扩展。最初出现于Windows 95简体中文版中,由于Windows产品的流行和在大陆广泛被使用,中华人民共和国国家有关部门将其作为技术规范。注意GBK并非国家正式标准,只是国家技术监督局标准化司、电子工业部科技与质量监督司发布的“技术规范指导性文件”。GBK字集是简繁字集,包括了GB字集、BIG5字集和一些符号,共包括21003个字符。
GBK作为对GB2312的扩展,在现在的windows系统中仍然使用代码页CP936表示,但是同样的936的代码页跟一开始的936的代码页只支持GB2312编码不同,现在的936代码页支持GBK的编码,GBK同时也向下兼容GB2312编码。
GB18030
2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,收录了藏文、蒙文、维吾尔文等主要的少数民族文字。现在的PC平台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。 GB18030在windows中的代码页是CP54936。

1.简体中文和繁体中文的转换

内码一般是指缺省代码页指定的编码,缺省代码页是默认用来解释字符的编码。简体中文windows系统缺省代码页是GBK。
ANSI编码:即所有在ASCII基础上扩充的字符编码的统称。在英文操作系统中ANSI是ASCII编码,繁体中文系统中ANSI是Big5编码,日文系统中ANSI是Shift_JIS编码,简体中文系统有点特殊,比如:editplus或记事本的默认编码为ANSI,但具体ANSI代表的是gbk还是gb2312还是gb18030,由这些编辑器根据码流去识别。window下很多文本编辑器都没有强行采用某种特定的编码,统一使用系统编码,所以中文win系统中ANSI就是GBK。
新建位图图像

GBK字符集包括了简体字符集、繁体字符集以及一些中文符号,当然同一汉字简繁字体在GBK下对应两种不同编码方式。可以,在ANSI编码下的简繁转化实质是在GBK编码表内的映射转化。
window头文件中提供了LCMapString function可以实现映射功能,程序如下

/*
 *作者:侯凯
 *说明:中文简繁的相互转化
 *日期:2013-6-18
 */
#include <Windows.h> 
#include <iostream>
using namespace std;

//中国->中國
char* Simple2Tra(char* szBuf)
{ 
    if(!strcmp(szBuf, ""))
        return NULL;
    int nReturn = LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_TRADITIONAL_CHINESE, szBuf, -1, NULL, 0);
    char *pcBuf = new char[nReturn];
    LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_TRADITIONAL_CHINESE, szBuf, -1, pcBuf, nReturn);
    return pcBuf;
}

//中國->中国
char* Tra2Simple(char* szBuf)
{ 
    if(!strcmp(szBuf, ""))
        return NULL;
    int nReturn = LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_SIMPLIFIED_CHINESE, szBuf, -1, NULL, 0);
    char *pcBuf = new char[nReturn];
    LCMapString(LOCALE_SYSTEM_DEFAULT, LCMAP_SIMPLIFIED_CHINESE, szBuf, nReturn, pcBuf, nReturn);
    return pcBuf;
}

void main()
{
    char* simWord = "中国";
    char* traWord = Simple2Tra(simWord);
    cout << simWord << "->" << traWord << endl;

    char* simWord2 = Tra2Simple(traWord);
    cout << traWord << "->" << simWord2 << endl;
}

LCMAP_SIMPLIFIED_CHINESE表示traditional Chinese字符集到simplified Chinese字符集的映射,LCMAP_TRADITIONAL_CHINESE相反。函数参数可参见msdn

2.简体中文和繁体中文(Big5)的转换

大多数情况下简繁的转化是GBK字符集内部的相互映射,但是有时我们会碰到另一种常见的繁体编码:“大五码”。Big5码是一套双字节字符集,BIG5码是通行于台湾、香港地区的一个繁体字编码方案,其对应代码页为950。首先来看繁体Big5繁体GBK编码的相互转化,它们二者通过Unicode字符集相关联,Big5<—>Unicode<—>GBK,类似思想可参见此文,程序实现如下

//中國->い瓣
//繁体GBK转Big5码
char* GBK2BIG5(char* szBuf)
{ 
    int wcsLen = ::MultiByteToWideChar(CP_ACP, NULL, szBuf, -1, NULL, 0);  
    wchar_t* wszString = new wchar_t[wcsLen];
    ::MultiByteToWideChar(CP_ACP, NULL, szBuf, -1, wszString, wcsLen); //CP_ACP本地编码(GBK)对应代码页

    int ansiLen = ::WideCharToMultiByte(950, NULL, wszString, -1, NULL, 0, NULL, NULL);
    char* szAnsi = new char[ansiLen];  
    ::WideCharToMultiByte(950, NULL, wszString, -1, szAnsi, ansiLen, NULL, NULL); //Big5对应代码页
    delete[] wszString;
    return szAnsi;  
}

//い瓣->中國
//Big5码转繁体GBK
char* BIG52GBK(char* szBuf)
{ 
    int wcsLen = ::MultiByteToWideChar(950, NULL, szBuf, -1, NULL, 0);  
    wchar_t* wszString = new wchar_t[wcsLen];
    ::MultiByteToWideChar(950, NULL, szBuf, -1, wszString, wcsLen); //Big5对应代码页

    int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, -1, NULL, 0, NULL, NULL);
    char* szAnsi = new char[ansiLen];  
    ::WideCharToMultiByte(CP_ACP, NULL, wszString, -1, szAnsi, ansiLen, NULL, NULL); //CP_ACP本地编码(GBK)对应代码页
    delete[] wszString;
    return szAnsi;  
}

上述程序实现了繁体字下GBK和Big5码的相互转化,由于简体中文操作系统中ANSI默认是GBK编码,“中國”二字转码为Big5码后,系统仍然按照GBK编码进行解析后显示,这样势必是乱码的。如果想要得到Big5编码下的正确显示,可以更改系统的语言,将Big5作为其默认ANSI即可,如下:打开“控制面板”->“区域和语言”
新建位图图像 (2)

重启计算机,台湾地区系统默认使用Big5码。如果刚才把GBK->Big5的结果保存到txt中,这时会发现txt文档中保存的“い瓣”变成了“中國”。在Big5编码下,有些大陆的网页可能会显示乱码,建议再改回原来的设置。
上述实现了繁体字GBK和Big5码的转化。如果想要将简体中文转化到Big5码,可以通过“简体中文GBK->繁体中文GBK->繁体Big5 ”的方式实现,第一步是GBK码内的映射,第二步是两种编码间的转化;反之亦然。

posted @ 2013-06-18 22:49  侯凯  阅读(7309)  评论(3编辑  收藏  举报