C/C++对Unicode编码的处理

一直都觉得C++对Unicode编码的处理比较麻烦,现就个人经验对这一方面做个总结。
Unicode编码
   在 计算机科学领域中, Unicode统一码万国码单一码标准万国码)是业界的一种标准,它可以使电脑得以呈现世界上数十种文字的系统。Unicode是基于 通用字符集(Universal Character Set)的标准来发展,并且同时也以书本的形式(The Unicode Standard,目前第五版由Addison-Wesley Professional出版,ISBN-10: 0321480910)对外发表。Unicode包含了超过十万个 字符(在 2005年,Unicode的第十万个字符被采纳且认可成为标准之一)、一组可用以作为视觉参考的代码图表、一套编码方法与一组标准 字符编码、一套包含了上标字、下标字等字符特性的列举等。
    Unicode的编码方式与 ISO 10646通用字符集(Universal Character Set,UCS)概念相对应,目前实际应用的Unicode版本对应于 UCS-2,使用16 的编码空间。也就是每个字符占用2个 字节。这样理论上一共最多可以表示2 16即65536个字符。基本满足各种语言的使用。实际上目前版本的Unicode尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
                                                                     (from wiki)
utf-8编码
 
    Unicode是一个标准。UTF-8是其概念上的子集,UTF-8是具体的编码标准。而Unicode是所有想达到
世界统一编码标准的标准。UTF-8标准就是Unicode(ISO10646)标准的一种变形方式, 
UTF的全称是:Unicode/UCS Transformation Format,其实有两种UTF,一种是UTF-8,一种是UTF-16, 
不过UTF-16使用较少,其对应关系如下:
在Unicode中编码为 0000 - 007F 的 UTF-8 中编码形式为: 0xxxxxxx 
在Unicode中编码为 0080 - 07FF 的 UTF-8 中编码形式为: 110xxxxx 10xxxxxx
在Unicode中编码为 0000 - 007F 的 UTF-8 中编码形式为: 1110xxxx 10xxxxxx 10xxxxxx

utf-8是unicode的一个新的编码标准,其实unicode有过好几个标准.我们知道一直以来使用的unicode字符内码都是16位,它实际上还不能把全世界的所有字符编在一个平面系统,比如中国的藏文等小语种,所以utf-8扩展到了32位,也就是说理论在utf-8中可容纳二的三十二次方个字符. UNICODE的思想就是想把所有的字符统一编码,实现一个统一的标准.big5、gb都是独立的字符集,这也叫做远东字符集,把它拿到德文版的WINDOWS上可能将会引起字符编码的冲突....
早期的WINDOWS默认的字符集是ANSI.notepad中输入的汉字是本地编码,但在NT/2000内部是可以直接支持UNICODE的。notepad.exe在WIN95和98中都是ANSI字符,在NT中则是UNICODE.ANSI和UNICODE可以方便的实现对应映射,也就是转换 ASCII是8位范围内的字符集,对于范围之外的字符如汉字它是无法表达的。unicode是16位范围内的字符集,对于不同地区的字符分区分配,unicode是多个IT巨头共同制定的字符编码标准。如果在unicode环境下比如WINDOWS NT上,一个字符占两字节16位,而在ANSI环境下如WINDOWS98下一个字符占一个字节8位.Unicode字符是16位宽,最多允许65,535字符,数据类型被称为WCHAR。 
对于已有的ANSI字符,unicode简单的将其扩展为16位:比如ANSI"A"=0x43,则对应的UNICODE为
"A"= 0x0043
而ASCII用七存放128个字符,ASCII是一个真正的美国标准,所以它不能满足其他国家的需要,例如斯拉夫语的
字母和汉字于是出现了Windows ANSI字符集,是一种扩展的ASCII码,用8位存放字符,低128位仍然存放原来的ASCII码, 而高128位加入了希腊字母等
if def UNICODE
  TCHAR = wchar
else
  TCHAR = char
你需要在Project\Settings\C/C++\Preprocesser definitions中添加UNICODE和_UNICODE 
UINCODE,_UNICODE都要定义。不定义_UNICODE的话,用SetText(HWND,LPCTSTR),将被解释为SetTextA
(HWND,LPTSTR),这时API将把你给的Unicode字符串看作ANSI字符串,显示乱码。因为windows API是已经编译好存在于dll中的,由于不管UNICODE还是ANSI字符串,都被看作一段buffer,如"0B A3 00 35 24 3C 00 00"如果按ANSI读,因为ANSI字串是以'\0'结束的,所以只能读到两字节"0B A3 \0",如果按UNICODE读,将完整的读到'\0\0'结束。
由于UNICODE没有额外的指示位,所以系统必须知道你提供的字串是哪种格式。此外,UNICODE好象是ANSI
C++规定的,_UNICODE是windows SDK提供的。如果不编写windows程序,可以只定义UNICODE。
                                                               (from WINODWS编码)
 
有关C++处理:
 
  在使用标标准C++编程时,其默认的编码方式是基于ANSCI。特别在处理文本数据时,一般常用的读写函数及字符处理都是用来处理ANSCII编码方式的,如:
ifstream
oftream
getline
string
   当然为了处理Unicode编码C++为每个字符处理函数提供了宽字符(wchar_t)处理函数。但实际使用这些完字符函数进行字符读写时达不到想要的结果,经常会出现乱码。所以在实际使用时一直都没法用上这些所谓的宽字符处理函数。为了达到目的,只要采用更加底层的C语言文件读写函数,以二进制的方式进行处理,如:
fread
fopen
fwrite
wchar_t
   举一个例子,我们需要将一个ANSCII码的文件转换为对应的Unicode文件,使用C++进行转换处理:
设输入文件:input.txt
  输出文件:output.txt
以如下方式打开这两个文件:
 
 FILE* output;
 ifstream input;

 input.open(sfile);//打开输入文件
 output=_wfopen(dfile,L"wb");//以宽字符模式打开输出文件
 if(!output)
 {
  cout<<"Can't open the output file:"<<dfile<<endl;
  exit(1);
 } 
 fwrite(L"\xFEFF",sizeof(wchar_t),1,output);//向输出文件写入UNICODE文件的开始标志
 if(!input)
 {
  cout<<"Can't open the input file:"<<sfile<<endl;
  exit(1);
 }
 
当将ANSCI编码的文件input读出来时,对其中的英文字符可以直接转换为宽字符而不会产生乱码:
 
outUnic[j]=wchar_t(inget[k])//inget[k]为ANSCI的英文字符,outUnic为其对应的UNICODE字符
 
对input中的中文字符,则不能直接转换,这样会出现乱码。对其中的中文字符需要使用Windows的API函数将中文内码转换为对应的Unicode编码:
//假设inget[i]和inget[i+1]中存有一个中文字符
   char p[2];
   wchar_t tUni[1];
   p[0]=inget[i];p[1]=inget[i+1];
   MultiByteToWideChar(CP_ACP,0,p,-1,tUni,1);//调用windows的API函数将中文内码转换成  UNICODE码
这个函数的具体参数可以查询MSDN,其功能为将多字符转换为宽字符,还对应有一个将宽字节转换为多字节的函数。
   outUnic[j++]=tUni[0];//tUni中为转换好的中文Unicode内码
 
当将读出的字符串转换为对应的Unicode字符串后,可按如下方式写入到output.txt 文件中:
fwrite( outUnic, sizeof( wchar_t), wstrlen(outUnic), output);
 
 
以上即为一个简单的C++对Unicode编码的处理,其过程远不如其它语言如java简洁。可能这也是C++的特色之处。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值