字符串编码小记

Posted 千羽;

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符串编码小记相关的知识,希望对你有一定的参考价值。

Ansi字符串我们最熟悉,英文占一个字节,汉字2个字节,以一个\\0结尾,常用于txt文本文件
Unicode字符串,每个字符(汉字、英文字母)都占2个字节,以2个连续的\\0结尾,NT操作系统内核用的是这种字符串,常被定义为typedef unsigned short wchar_t;所以我们有时常会见到什么char*无法转换为unsigned short*之类的错误,其实就是unicode
UTF8是Unicode一种压缩形式,英文A在unicode中表示为0x0041,老外觉得这种存储方式太浪费,因为浪费了50%的空间,于是就把英文压缩成1个字节,成了utf8编码,但是汉字在utf8中占3个字节,显然用做中文不如ansi合算,这就是中国的网页用作ansi编码而老外的网页常用utf8的原因。


ANSI 编码

ANSI一种字符代码,为使计算机支持更多语 言,通常使用0x80~0xFF 范围的2 个字节来表示1 个字符。不同的国家和地区制定了不同的标准,由此产生了GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码标准。 这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI 编码。

关于MBCS字符集(Multi Byte Character System):GB2312、GBK等编码被称为MBCS,MBCS同ASCII是完全兼容的。对于前ASCII的128个字符,在MBCS字符集下有完全相同的编码,而汉字等字符用多个字节存储。也意味着MBCS下,字符的长度有可能有1个字节的,也有多个字节的。

所以ANSI编码其实是一个统称,不同的语言使用不同的编码规范,并没有跨语言统一编码。比如 windows7 notepad记事本保存的时候,在弹出对话框的下方有“编码”下拉框,默认是“ANSI”,也可以选择“Unicode”(其实是UTF-16)和 “UTF-8”。如果选择了ANSI,那么实际使用的编码规范就跟你的操作系统版本强相关了,如果是简体中文的windows就会用GBK标准。

Unicode编码

就是把地球上所有的语言的符号,都用统一的字符集来表示,一个编码真正做到了唯一。Unicode只是确定了字符的二进制编码,但并没有确定字符存储的具体实现方式。比如UTF-8 ,UTF16是常见的Unicode实现方式。

UTF-8编码是变长的,一个字符可能是1个字节,2个字节,3个字节或者4个字节长。一般来说,欧洲的字母字符长度为1到2个字节,而亚洲的大部分字符则是3个字节,附加字符为4个字节长。Unix平台中普遍支持UTF-8字符集,html和大多数浏览器也支持UTF-8。

UTF-16编码的字符,要么是2个字节,要么是4个字节表示的。windows2000以上版本使用UTF-16,老版本windows用的ANSI。

VC下的格式转换
ANSI字符串转Unicode(windows下对应UTF-16编码)
在vc工程选择unicode编译的情况下,如果是字符串常量可以直接使用L和_T or _TEXT宏,也可以使用wsprintf函数进行转换(需要引用Windows.h)。

复制代码

    TCHAR szW[100]; 
//all strings are Unicode 
    swprintf(szW,L"%s",L"Unicode Str中文"); 
    CString name = _T("Report.txt"); 
//ANSI to Unicode,wsprintf可以直接用,使用大写的%S 
//注意swprintf函数是不行的,据说要先加setlocale(LC_CTYPE, "chs")语句 
    wsprintfW(szW,L"%S","Unicode Str中文");

复制代码

如果是字符串变量,使用ATL 提供的字符转换宏会比较方便,也可以使用wsprintf函数。

复制代码

char buff[512]; 
//获取工作目录的路径,ANSI编码,路径中的中文字符占用2个字节 
    std::string s_currPath = _getcwd(buff,512); 
    TCHAR szW[512]; 
    USES_CONVERSION; 
//注意使用A2W宏,不可直接调用swprintf_s(szW,512,L"%S",...) 
    swprintf_s(szW,512,L"%s",A2W(s_currPath.c_str())); 
//wsprintf可以直接使用
    wsprintfW(szW,L"%S",s_currPath.c_str());

复制代码

Unicode转ANSI
和上面类似,使用ATL的宏W2A即可。或者使用wsprintfA(sA, "%S", L"中文"),其中sA是char数组。
另外,转换还可以使用功能更强大的WideCharToMultiByte函数和MultiByteToWideChar函数。

C++11与Unicode

C++11对Unicode提供了语言级别和库级别的支持,可以进行Unicode下不同编码方式的转换,我也没玩过,可以参考这篇blog:

http://blog.poxiao.me/p/unicode-character-encoding-conversion-in-cpp11/

以上是关于字符串编码小记的主要内容,如果未能解决你的问题,请参考以下文章

字符编码及java中的应用总结小记

邓白氏编码申请小记

iOS开发小记(十三)

Java 基本数据类型 编码方式(小记1.7)

信息论小记

关于JS中字符串的编码