字符编码

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的用处就是定长表示世界文字,据统计,用两个字节可以编码 
现存的所有文字而没有二义。

3Windows下的程序设计可以支持ANSIUnicode两种编码方法的字符串,具体使用哪种就要看定义了

MBCS宏还是Unicode宏。MBCS宏对应的字符串指针为LPSTR(即char*),Unicode对应的指针为

LPWSTR(即unsigned char*)。为了写程序的方便,微软定义了类型LPTSTR,在MBCS下它表示char*

Unicode下它表示unsignedchar*,这就可以重定义一个宏进行不同字符集的转换了。

7_T是一个适配宏。当定义了_UNICODE时,_TL相同;否则,_T的字符串采用ANSI编码方式。示例如

下:

    LPTSTRlptStr=new TCHAR[32];

    TCHAR*szBuf=_T("Hello");

    以上两个语句,无论是在ANSI编码方式,还是在Unicode编码方式下都是正确的。

8、微软推荐使用相匹配的字符串函数。例如,在处理LPTSTRLPCTSTR的时候,应该使用_tcslen来替

strlen函数。否则,在Unicode编码方式下,strlen不能处理wchar_t*的字符串。

9T是一个非常重要的符号(TCHARLPTSTRLPCTSTR_T()_TEXT()等),它表示使用一个中间

类型,既不明确表示使用MBCS,也不明确表示使用Unicode。到底使用哪种字符集,在编译的时候才决

定。

4、Windows使用两种字符集ANSIUnicode,前者在处理英文字符时使用单字节方式,在处理中文字符时

使用双字节方式。后者不管是英文字符还是中文字符都是采用双字节方式表示。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、

只定义了宏并不能实现自动的转换,他还需要一系列的字符定义支持。

1TCHAR

如果定义了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, //代码页:ANCI
DWORD dwFlags, //一般传0
LPCSTR lpMultiByteStr, //多字节字符
int cchMultiByte, //长度,一般传 -1
LPWSTR 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。
 

你可能感兴趣的:(字符编码)