0、字符集:二进制到字符编码就是字符集。
0、ANSI:为多字节字符集,它是不定长表示世界文字的编码方式。ANSI表示英文字母时就和 ASCII一样,但表示其他文字时就需要用多字节。它代表本地字符集,在中文操作系统上就是GBK,到了日本就变成了JIS了。就会读成了乱码。
1
、
ANSI
(即
MBCS
)
:为多字节字符集,它是不定长表示世界文字的编码方式。
ANSI
表示
英文字母时就和
ASCII
一样,但表示其他文字时就需要用多字节。
1、ASCII:美国信息交换标准码 (ASCII),标准的单字节字符编码方案,用于基于文本的数据。
由于ASCII字节的七个位,最高位并不使用,始终是0。范围0 —— 127。所以后来又将最高的一个位也编入这套内码中,成为八个位的延伸ASCII (ExtendedASCII)码,这套内码加上了许多外文和表格等特殊符号,成为目前常用的内码。
2、Unicode:用两个字节表示一个字符的编码方式。比如字符'A'在ASCII下面用一个字节表示,而在
Unicode下面用两个字节表示,其中高字节用“0”填充;函数'程'在ASCII下面用两个字节表示,而在
Unicode下面也是用两个字节表示。Unicode的用处就是定长表示世界文字,据统计,用两个字节可以编码
现存的所有文字而没有二义。
3、Windows下的程序设计可以支持ANSI和Unicode两种编码方法的字符串,具体使用哪种就要看定义了
MBCS宏还是Unicode宏。MBCS宏对应的字符串指针为LPSTR(即char*),Unicode对应的指针为
LPWSTR(即unsigned char*)。为了写程序的方便,微软定义了类型LPTSTR,在MBCS下它表示char*,
在Unicode下它表示unsignedchar*,这就可以重定义一个宏进行不同字符集的转换了。
7、_T是一个适配宏。当定义了_UNICODE时,_T和L相同;否则,_T的字符串采用ANSI编码方式。示例如
下:
LPTSTRlptStr=new TCHAR[32];
TCHAR*szBuf=_T("Hello");
以上两个语句,无论是在ANSI编码方式,还是在Unicode编码方式下都是正确的。
8、微软推荐使用相匹配的字符串函数。例如,在处理LPTSTR或LPCTSTR的时候,应该使用_tcslen来替
代strlen函数。否则,在Unicode编码方式下,strlen不能处理wchar_t*的字符串。
9、T是一个非常重要的符号(TCHAR、LPTSTR、LPCTSTR、_T()和_TEXT()等),它表示使用一个中间
类型,既不明确表示使用MBCS,也不明确表示使用Unicode。到底使用哪种字符集,在编译的时候才决
定。
4、Windows使用两种字符集ANSI和Unicode,前者在处理英文字符时使用单字节方式,在处理中文字符时
使用双字节方式。后者不管是英文字符还是中文字符都是采用双字节方式表示。Windows NT的所有与字符
如_T("你好!");。如果编码方式为ANSI,_T不起任何作用;如果编码方式为Unicode,编译器会把"你好!"以Unicode方式进行保存。_T和_L的区别在于,_L不管你是以什么方式编译,一律以Unicode方法保存。
5、
ANSI:即 char,可用字符串处理函数:strcat( ),strcpy( ),strlen( )等以str打头的函数。
UNICODE:即wchar_t 可用字符串处理函数:wcscat(),wcscpy(),wcslen()等以wcs打头的函数。
6、
在C语言里面提供了_UNICODE宏(有下划线),在Windows里面提供了UNICODE宏(无下划线),只要定了_UNICODE宏和UNICODE宏,系统就会自动切换到UNICODE版本,否则,系统按照ANSI的方式进行编译和运行。
7、
只定义了宏并不能实现自动的转换,他还需要一系列的字符定义支持。
1.TCHAR
如果定义了UNICODE宏则TCHAR被定义为wchar_t。
typedef wchar_t TCHAR;
否则TCHAR被定义为char
typedefchar TCHAR;
LPTSTR
如果定义了UNICODE宏则LPTSTR被定义为LPWSTR。
typedef LPTSTR LPWSTR;
否则TCHAR被定义为char
typedefLPTSTR LPSTR;
8、
C 程序员一般是用 char 关键字象下面这样来声明一个字符串数组:
char str[100];
象下面这样声明函数原形:
void strcpy( char *out, char *in );
为了将上面的声明改成支持双字节的 UNICODE 字符集,可以用下面的方法:
wchar_t str[100];
或者
void wcscpy( wchar_t *out,wchar_t *in );在代码中,凡是用关键字 char 的地方都用 TCHAR 取代;凡是用 char * 的地方都用 LPTSTR 取代;凡是定义在双引号中的字符串常量(如"VCKBASE Online Journal")都用TEXT 宏重写:
TEXT("VCKBASE OnlineJournal");
TEXT 宏的主要作用是当定义了 UNICODE/_UNICODE 预处理指令时,字符串被标志为双字节字符串,否则字符串被标示为 ANSI 字符串。TEXT 的定义如下:
TEXT(
LPTSTR string // ANSI 或者Unicode 字符串
);
2、GB2312:用两个字节来表示中文。
问题:238 97 245 97 。这里是把238 97 当作中文,还是把97当做一个英文呢?如何划分?
单字节小于127的,正好是ASCII码值。那如何兼容ASCII码呢??
解决办法:GB2312完全不占用0-127。只占用[129——255],的字符。就不存在和ASCII码冲突的问题了。但是这样只有10000多个字符。实际只容纳了6000多个汉字。不够大。
3、GBK:还是双字节。那是如何扩充容量的呢?——GBK的第二个字节,不在局限于[129——255],可以在[0 ——255]。
4、问题:GBK到了日本去了怎么办?编码不一样了。就不兼容了。
5、MBCS:多字节字符集,字符串有1个或者2个直接宽。strlen得到的是字节数,而不是字符串长度。
6、Unicode:通用、统一、固定长度。全世界的字符都有唯一的表示。不管英语还是中文都是2个字节。
Unicode字符串加前缀L表示。
Unicode用4个字节来分配每个字符的编号。但是常用的,集中在65536个标号里面,只要2个字节就足够了。
于是有了简化的编号。把高位浪费的一些0值用一定的规则舍弃掉。只有经过 了简化的才可以在网络上传输。
于是有了UTF-8。Unicode与UTF-8类似于文件和压缩文件的关系。
UTF-8占用几个字节呢?——不是固定的,根据特定的范围,1-6个字节表示。
那如何确定字符的边界呢?最高位确定!!!
如何截取UTF-8,不一定全中文,无乱码!——第一个字节位运算获得1的个数。
问题:GBK转UTF-8如何转的。先转Unicode,再转UTF-8。
问题:乱码是如何形成的?
(1)解码时,与实际编码方式不一致。
(2)传输过程中,UTF-8转成GB2312,会导致编码丢失。
Unicode程序直接使用Unicode版本的CRT和Win32 API。Unicode程序的运行与当前的ANSI代码页没有关系。MBCS程序的运行依赖于ANSI代码页。如果设计者和使用者使用不同的代码页,就可能出现乱码。微软开发的程序大都是Unicode程序,不管我们怎样变换系统Locale,它们总能正常运行。
例如Windows的标准对话框也会出现乱码。假设我们使用简体中文Windows,当前Locale是Chinese (TW),我们的程序是MBCS的,使用标准的打开文件对话框。因为在BIG5中没有“开”这个字,所以“打开”会被显示成“打?”。将程序编译成Unicode版本,就可以避免这个问题。
如果字符不是保存在资源中,而是硬编码在程序中。然后开发者和用户使用不同的代码页,就会导致乱码。假设开发者的Locale是Chinese (PRC),用户的Locale是English (US),程序中硬编码了字符串“文件”。 Chinese (PRC)的ANSI代码页是GBK,“文件”的编码“CE C4 BC FE”。English (US)的ANSI代码页是Latin I,用户按照Latin I编码去解释“CE C4 BC FE”,就会看到“Îļþ”
7、Unicode与ANSI转换:
int MultiByteToWideChar(UINT CodePage, //代码页:ANCIDWORD dwFlags, //一般传0LPCSTR lpMultiByteStr, //多字节字符int cchMultiByte, //长度,一般传 -1LPWSTR lpWideCharStr, //Out,保存得到的宽字节。int cchWideChar //输入);
用法示例:
char srGb[] = “大小”;
wchar_t* pst;
char* pstBig;
int iLen;
iLen = MultiByteToWideChar(CP_ACP,0,srGb,-1,NULL,0);//获得要转换的长度
pstBig = new wchar_t(iLen+1);
MultiByteToWideChar(CP_ACP,0,srGb,-1,pstBig,iLen); //将GB2312转成Unicode。