C++之多字节字符集与Unicode字符集
  在计算机中字符通常并不是保存为图像,每个字符都是使⽤⼀个编码来表⽰的,⽽每个字符究竟使⽤哪个编码代表,要取决于使⽤哪个字符集(charset)。
多字节字符集:
  在最初的时候,Internet上只有⼀种字符集——ANSI的ASCII字符集,它使⽤7 bits来表⽰⼀个 字符,总共表⽰128个字符,其中包括了 英⽂字母、数字、标点符号等常⽤字符。之后,⼜进⾏扩展,使⽤8 bits表⽰⼀个字符,可以表⽰256个字符,主要在原来的7 bits字符集的基础上加⼊了⼀些特殊符号。后来,由于各国语⾔的加⼊,ASCII已经不能满⾜信息交流的需要,为了能够表⽰其它国家的⽂字,各国在 ASCII的基础上制定了⾃⼰的字符集,这些从ANSI标准派⽣的字符集被习惯的统称为ANSI字符集,它们正式的名称应该是MBCS(Multi-Byte Chactacter System,即多字节字符系统)。这些派⽣字符集的特点是以ASCII 127 bits为基础,兼容ASCII 127,他们使⽤⼤于128的编码作为⼀个Leading Byte,紧跟在Leading Byte后的第⼆(甚⾄第三)个字符与 Leading Byte⼀起作为实际的编码。这样的字符集有很多,我们常见的GB-2312就是其中之⼀。
Unicode字符集:
  Unicode的学名 是"Universal Multiple-Octet Coded Character Set",简称为UCS。UCS可以看作是"Unicode Character Set"的缩写。UCS只是规定如何编码,并没有规定如何传输、保存这个编码。UTF是“UCS Transformation Format”的缩写。
  Unicode字符集有多种编码形式,它固定使⽤16 bits(两个字节、⼀个字)来表⽰⼀个字符,共可以表⽰65536个字符。将世界上⼏乎所有语⾔的常⽤字符收录其中,⽅便了信息交流。标准的Unicode称为UTF-16。后来为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8(注意UTF-8是编码,它属于Unicode字符集),使⽤类似MBCS的⽅式对Unicode进⾏编码。UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元。
  UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian),UTF-16需要通过在⽂件开头以名为BOM(Byte Order Mark)的字符来表明⽂件是Big Endian还是Little Endian。Unicode规范中推荐的标记字节顺序的⽅法是BOM(Byte Order Mark)。在UCS编码中有⼀个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。⽽FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"⼜被称作BOM。
  UTF-8不需要BOM来表明字节顺序,但可以⽤BOM来表明编码⽅式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以⽤我们前⾯介绍的编码⽅法验证⼀下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
  Windows就是使⽤BOM来标记⽂本⽂件的编码⽅式的。
  L是⽤来标志⼀个字符(串)为宽字符(串),当你在VS2005以上版本的IDE⼯作时,可以选择⼯作于这两种不同的编码⽅式下,⽽在Unicode⽅式下,则要对字符(串)常量前添加L来告诉编译器它是宽字符。MS为我们定义了好⼏个相关的宏:_T(定义于tchar.h)、
_TEXT(同样定义于tchar.h)。
  TEXt():如果定义了Unicode,标识字符为Unicode;否则,为ANSI字符集。在VS2010使⽤Unicode字符集下:
//    MessageBox("Test");  //错误
//    MessageBox(_T("Test"));
//    MessageBox(TEXT("Test"));
MessageBox(_TEXT("Test")); 
  对于为什么使⽤Unicode?(以下引⾃《windows核⼼编程》)
  开发应⽤程序的时候,强烈建议你使⽤Unicode字符和字符串,理由如下:
Unicode使程序的本地化变得更容易;
使⽤Unicode,只需发布⼀个⼆进制(.exe或DLL)⽂件,即可⽀持所有语⾔;
数字转unicode编码Unicode代码执⾏速度更快,占⽤内存更少,提升了应⽤程序的效率。⾃从Windows2K开始,Win的系统内核开始完全⽀持并完全应⽤Unicode编写,所有ANSI字符在进⼊底层前,都会被相应的API转换成Unicode。所以,如果你⼀开始就使⽤Unicode,则可以减少转换的⽤时和RAM开销。
使⽤Unicode,你的应⽤程序能轻松调⽤所有不反对使⽤(nondeprecated)的Windows函数,因为⼀些Windows函数提供了只能处理Unicode字符和字符串的版本;
使⽤Unicode,你的代码很容易与COM集成(后者要求使⽤Unicode字符和字符串);
使⽤Unicode,你的代码很容易与.NET Framework集成(后者要要求使⽤Unicode字符和字符串);
使⽤Unicode,能保证你的代码能够轻松操纵你⾃⼰的资源(其中的字符串总是Unicode的);
世界上⼤多数程序⽤的字符集都是Unicode,因为Unicode有利于程序国际化和标准化;
  wchar_t与char类型间的转换:
#include<iostream>
#include<Windows.h>
using namespace std;
class CUser
{
public:
CUser();
virtual ~CUser();
char* WcharToChar(wchar_t* wc);//宽字节转单字节
wchar_t* CharToWchar(char* c); //单字节转宽字节
void Release();//释放资源
private:
char* m_char;
wchar_t* m_wchar;
};
/
/*字符类型        wchar_t    char
/*获取字符长度    wcslen()    strlen()
/*连接两个字符串  wcscat()    strcpy()
/
*复制字符串      wcscpy()    strcpy()
/*⽐较两个字符串  wcscmp()    strcmp()
/*具体参数详见www.linuxidc*/
CUser::CUser():m_char(NULL),m_wchar(NULL)
{
}
CUser::~CUser()
{
Release();
}
//宽字节转单字节
char* CUser::WcharToChar(wchar_t* wc)
{
Release();
int len= WideCharToMultiByte(CP_ACP,0,wc,wcslen(wc),NULL,0,NULL,NULL);
m_char=new char[len+1];
WideCharToMultiByte(CP_ACP,0,wc,wcslen(wc),m_char,len,NULL,NULL);
m_char[len]='\0';
return m_char;
}
//单字节转宽字节
wchar_t* CUser::CharToWchar(char* c)
{
Release();
int len = MultiByteToWideChar(CP_ACP,0,c,strlen(c),NULL,0);
m_wchar=new wchar_t[len+1];
MultiByteToWideChar(CP_ACP,0,c,strlen(c),m_wchar,len);
m_wchar[len]='\0';
return m_wchar;
}
//释放资源
void CUser::Release()
{
{
if(m_char)
{
delete m_char;
m_char=NULL;
}
if(m_wchar)
{
delete m_wchar;
m_wchar=NULL;
}
}
使⽤如下:
WCHAR* wc;
CUser u;
char* c=u.WcharToChar(wc);  cout<<c<<endl;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。