为什么要Unicode?
ANSI用
一个字节(8位)
表示一个字符
但是很多世界上其他的语言无法表示,但是又想每个字符都平等对待,所以需要更长的位
Unicode用
两个字节(16位)来
表示一个国际字符,这样世界上任何国家的任何字符都可以用两个字节统一表示
对C++而言如何表示Unicode?
char正好是
8位,可以用来表示一个ANSI字符
wchar_t正好是
16位,可以表示一个Unicode字符
Unicode统一码?
Unicode: 统一码,包含世界上各个国家的全部语言文字,字符。1994年出第一版。
标准内容是每一个字符的序号ID。
范围:
目前的Unicode字符分为17组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1,114,112个
从Unicode ID到内存表示?
Unicode仅仅规定了一个Unicode字符的序号,并没有规定在内存中用几个字节,
是否固定字节还是变长字节。
所以,Unicode在内存中的实现有常见的两种方式,变长编码,定长编码。
定长与变长UTF-8?
(1)变长编码:多个字节表示一个字符,UTF-8:char:string:,适合网络传输(压缩原理:经常使用的字符用较少字节,不经常使用的字符用较多字节表示)
(2)定长编码:两个字节表示一个字符,UTF-16:wchar_t :wstring:
CString同时支持两种不同的Unicode内存表示
CString使用TCHAR中间类型,由编译选项来决定是char 还是wchar_t
_T("中间类型的字符串");最终生成代码是wchar_t还是char取决于编译选项是Unicode还是多字节,所以代码中都应该使用中间类型字符串_T("")
宽字符初始化L"",L是用来初始化一个wchar_t字符串常量的。char 字符串常量的初始化只需要""双引号即可。
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
(1)
编译选项如果设置为Unicode:CString<-
TCHAR<-
WCHAR<-
wchar_t<-wstring.c_str()
(2)
编译选项如果设置为多字节:CString<-
TCHAR<-
char<-string.c_str()
UTF-8编码在两种编译选项下CString与string之间的转换:
(1)Unicode:此时CString使用wchar_t表示q
string转CString:
CString().Format("%s",string.c_str());//wchar_t只存储一个char的内容,此时多字节的UTF-8中的每一个字节(而不是每一个字符)就会被CString当做是一个UTF-16字符,从而产生乱码
正确的做法是
使用MultiByteToWideChar系统函数进行转换:将多字节的每一个字符(多字节的字符)转换为一个固定长(wchar_t保存)的字符(UTF-16)
CString转string
同样的需要转码:WideCharToMultiByte
(2)多字节:此时CString使用char表示,所以本质上(编码与存储方式)是相同的
CString cs(L"中国");
std::cout<<cs.GetBuffer()<<std::endl;//中国
std::string s(cs.GetBuffer());
std::cout<<s.c_str()<<std::endl;//中国
CString cs_from_str(s.c_str());
std::cout<<cs_from_str.GetBuffer()<<std::endl;
上面的代码在Unicode下面
不能通过编译:wchar_t不能和char不能进行隐式类型转换
Windows转码函数:
CString与string之间的转换
//std::string UnicodeToANSI( const std::wstring& str )
//{
//
// char* pElementText;
// int iTextLen;
// // wide char to multi char
// iTextLen = WideCharToMultiByte( CP_ACP,
// 0,
// str.c_str(),
// -1,
// NULL,
// 0,
// NULL,
// NULL );
// pElementText = new char[iTextLen + 1];
// memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
// ::WideCharToMultiByte( CP_ACP,
// 0,
// str.c_str(),
// -1,
// pElementText,
// iTextLen,
// NULL,
// NULL );
// std::string strText(pElementText);
// delete[] pElementText;
// return strText;
//}
//std::wstring ANSIToUnicode( const std::string& str )
//{
// int len = 0;
// len = str.length();
// int unicodeLen = ::MultiByteToWideChar( CP_ACP,
// 0,
// str.c_str(),
// -1,
// NULL,
// 0 );
// wchar_t * pUnicode;
// pUnicode = new wchar_t[unicodeLen+1];
// memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
// ::MultiByteToWideChar( CP_ACP,
// 0,
// str.c_str(),
// -1,
// (LPWSTR)pUnicode,
// unicodeLen );
// std::wstring rt(( wchar_t* )pUnicode);
// delete pUnicode;
//
// return rt;
//}