多字节与宽字节

  • 多字节字符集(MBCS,Multi-Byte Chactacter Set):指用多个字节来表示一个字符的字符编码集合。一般英文字母用1Byte,汉语等用2Byte来表示。兼容ASCII 127。

在最初的时候,Internet上只有一种字符集——ANSI的ASCII字符集,它使用7 bits来表示一个 字符,总共表示128个字符,其中包括了 英文字母、数字、标点符号等常用字符。

为了扩充ASCII编码,以用于显示本国的语言,不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码,又称为"MBCS(Muilti-Bytes Charecter Set,多字节字符集)"。

不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。一个很大的缺点是,同一个编码值,在不同的编码体系里代表着不同的字。这样就容易造成混乱。导致了unicode码的诞生。

  • 宽字节字符集:一般指Unicode编码的字符集,

Unicode称为统一码或万国码,统一了不同国家的字符编码。

Unicode通常用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只需要把高字节全部填为0就可以。

为了统一所有文字的编码,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。

Unicode固然统一了编码方式,但是它的效率不高,比如UCS-4(Unicode的标准之一)规定用4个字节存储一个符号,那么每个英文字母前都必然有三个字节是0,这对存储和传输来说都很耗资源。为了提高Unicode的编码效率,于是就出现了UTF-8编码。UTF-8可以根据不同的符号自动选择编码的长短。比如英文字母可以只用1个字节就够了。

UTF是“Unicode Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。用char、char16_t、char32_t分别表示无符号8位整数,无符号16位整数和无符号32位整数。UTF-8、UTF-16、UTF-32分别以char、char16_t、char32_t作为编码单位。(注: char16_t 和 char32_t 是 C++ 11 标准新增的关键字。如果你的编译器不支持 C++ 11 标准,请改用 unsigned short 和 unsigned long。)“汉字”的UTF-8编码需要3个字节。“汉字”的UTF-16编码需要两个char16_t,大小是2个字节。“汉字”的UTF-32编码需要两个char32_t,大小是4个字节。

普通字符、字符串前加 L 就变成宽字符 wchar_t 存储(用2Byte存1个字符)了,例如,L‘看’,L"abc啊";或_T("sf飞")


MFC中的 CString 与 std::string 的转换:

1. 使用Unicode字符集时,CString等价于CStringW;使用多字节字符集时,CString相对于CStringA

2. CString --> std::string

// 1. Unicode下 CString --> std::string
// 方法1
CString str = L"sdf";
std::string s = CT2A(str.GetString());
    // GetString()比较新的VS有,旧可以用GetBuffer()
    std::string s = CT2A(str.GetBuffer());
    str.ReleaseBuffer();
// 方法2
CString str = L"dshf";
CStringA stra(str);
std::string s(stra);
//或
std::string s(CStringA(str));

//方法3
USES_CONVERSION;
CString str = L"djg";
std::string s = W2A(str);
//首先str--》const wchar_t* ,然后W2A将const wchar_t*--》const char*,
//最后用const char*初始化s

 

 3. std::string --> CStringW / std::wstring

std::string s("dhhh");
CStringW strw(CStringA(s.c_str());
std::wstring sw(strw);

  


1)TCHAR 转换为const wchar_t *,直接强制转换,在TCHAR前面加上(*const wchar_t)

2)BSTR:是一个OLECHAR*类型的Unicode字符串,是一个COM字符串,带长度前缀,与VB有关,没怎么用到过。 

LPSTR:即 char *,指向以'/0'结尾的8位(单字节)ANSI字符数组指针 

LPWSTR:即wchar_t *,指向'/0'结尾的16位(双字节)Unicode字符数组指针 

 LPCSTR:即const char * 

 LPCWSTR:即const wchar_t * 

LPTSTR:LPSTR、LPWSTR两者二选一,取决于是否宏定义了UNICODE或ANSI 

LPCTSTR: LPCSTR、LPCWSTR两者二选一,取决于是否宏定义了UNICODE或ANSI,

如下是从MFC库中拷来的:

#ifdef UNICODE 
typedef LPWSTR LPTSTR; 
typedef LPCWSTR LPCTSTR;
#else 
typedef LPSTR LPTSTR; 
typedef LPCSTR LPCTSTR; 
#endif

  

 相互转换方法:

LPWSTR->LPTSTR:      W2T();
 LPTSTR->LPWSTR:     T2W(); 
LPCWSTR->LPCSTR:   W2CT();
 LPCSTR->LPCWSTR:   T2CW();
 ANSI->UNICODE:   A2W();
 UNICODE->ANSI:   W2A();

3)

LPWSTR转为LPCSTR

LPCSTR=CW2A(LPWSTR);

 4)

CString与LPCWSTR的转化(http://www.cnblogs.com/foolboy/archive/2005/07/25/199869.html)

问题起因: 
    在写WritePrivateProfileString写.ini配置文件时在msdn中看到,如果想要写的配置信息即时生效,必须在之前使用WritePrivateProfileStringW来re-read一下目标.ini文件,其原文如下: 

// force the system to re-read the mapping into shared memory  
// so that future invocations of the application will see it  
//  without the user having to reboot the system  
WritePrivateProfileStringW( NULL, NULL, NULL, L"appname.ini" );

  

    查了一下msdn中WritePrivateProfileStringW的原型如下: 

WINBASEAPI BOOL WINAPI WritePrivateProfileStringW ( 
 LPCWSTR lpAppName,  //section []中的字符串
 LPCWSTR lpKeyName,  // key  “=”左边的字符串
 LPCWSTR lpString,   //写入的内容
 LPCWSTR lpFileName ) // 配置文件的路径
例如:
[section]
key=string

  其中的每个参数的类型都为LPCWSTR,实际中获得的文件名都为CString,问题产生。 

问题分析:

LPCWSTR 是Unicode字符串指针,初始化时串有多大,申请空间就有多大,以后存储若超过则出现无法预料的结果,这是它与CString的不同之处。而CString是一个串类,内存空间类会自动管理。LPCWSTR 初始化如下: 

LPCWSTR Name=L"TestlpCwstr";

    由于LPCWSTR必须指向Unicode的字符串,问题的关键变成了Anis字符与Unicode字符之间的转换,不同编码间的转换,通过查找资料可知,可以ATL中转换宏可以用如下方法实现: 

//方法一 
CString str=_T("TestStr"); 
USES_CONVERSION; 
LPWSTR pwStr=new wchar_t[str.GetLength()+1]; 
wcscpy(pwStr,T2W((LPCTSTR)str));
 
// 方法二 
CString str=_T("TestStr"); 
USES_CONVERSION; 
LPWCSTR pwcStr = A2CW((LPCSTR)str);

  MFC中CString和LPSTR是可以通用,其中A2CW表示(LPCSTR)  -> (LPCWSTR),USER_CONVERSION表示用来定义一些中间变量,在使用ATL的转换宏之前必须定义该语句。 
    顺便也提一下,如果将LPCWSTR转换成CString,那就更加容易,在msdn中的CString类说明中提到了可以直接用LPCWSTR来构造CString,所以可以进行如下的转换代码:   

LPCWSTR pcwStr = L"TestpwcStr"; 
CString str(pcwStr);

问题总结:     
    在头文件<atlconv.h>中定义了ATL提供的所有转换宏,如:    

  A2CW      (LPCSTR)  -> (LPCWSTR) 
  A2W        (LPCSTR)  -> (LPWSTR) 
  W2CA     (LPCWSTR) -> (LPCSTR) 
  W2A        (LPCWSTR) -> (LPSTR)

     所有的宏如下表所示: 

A2BSTROLE2AT2AW2A
A2COLEOLE2BSTRT2BSTRW2BSTR
A2CTOLE2CAT2CAW2CA
A2CWOLE2CTT2COLEW2COLE
A2OLEOLE2CWT2CWW2CT
A2TOLE2TT2OLEW2OLE
A2WOLE2WT2WW2T

上表中的宏函数,非常的有规律,每个字母都有确切的含义如下:

2to 的发音和 2 一样,所以借用来表示“转换为、转换到”的含义。
AANSI 字符串,也就是 MBCS。
W、OLE宽字符串,也就是 UNICODE。
T中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A
Cconst 的缩写

    利用这些宏,可以快速的进行各种字符间的转换。使用前必须包含头文件,并且申明USER_CONVERSION;使用 ATL 转换宏,由于不用释放临时空间,所以使用起来非常方便。但是考虑到栈空间的尺寸(VC 默认2M),使用时要注意几点: 
    1、只适合于进行短字符串的转换; 
    2、不要试图在一个次数比较多的循环体内进行转换; 
    3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的; 
    4、对情况 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();

MultiByteToWideChar() 和 WideCharToMultiByte()的用法:
www.cnblogs.com/ranjiewen/p/5770639.html

int MultiByteToWideChar(
  UINT CodePage, //指定执行转换的多字节字符所使用的字符集,CP_ACP:ANSI字符集,CP_UTF8:UTF-8字符集
  DWORD dwFlags, // 一般为NULL
  LPCSTR lpMultiByteStr, // [in] 要被转换的字符指针
  int cchMultiByte,  // lpMultiByteStr指针指向的字符串的长度,若字符串以\0结尾,可简单写为 -1
  LPWSTR lpWideCharStr, //[out] 输出的宽字符串指针
  int cchWideChar  // 指定由参数lpWideCharStr指向的缓冲区的宽字符数。若此值为0,函数不会执行转换,而是返回目标缓存lpWideChatStr所需的宽字符数。
  );

int WideCharToMultiByte(
UINT CodePage,  //指定执行转换的字符集
DWORD dwFlags,  // NULL
LPCWSTR lpWideCharStr, // 待转换的字符串
int cchWideChar, // 待转换的字符串长度,若以空字符结尾,则可写-1
LPSTR lpMultiByteStr, // 指向接收被转换字符串的缓冲区
int cbMultiByte,  // 缓冲区的长度,若为0,函数返回接收的缓冲区的长度
LPCSTR lpDefaultChar, // NULL
LPBOOL lpUsedDefaultChar //NULL
);

  

转载于:https://www.cnblogs.com/htj10/p/11027323.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值