学习
unicode
也有一段时间了,虽然说没有学得很好,但是却是学到了许多东西啊,所以稍微小结一下,免得忘了,呵呵。很早就接触过
unicode
这个词了。不过以前太天真了,以为
unicode
是一件非常简单的事情,很容易就解决了。只要用
TCHAR
代替
CHAR
,在所有的字符串前面加上
TEXT
,然后在
vc
里面
Preprocessor definitions
加上
_UNICODE
,
UNICODE
就
OK
了。实际上,仅仅这样,还有很多疑惑不能解决。
1、
Windows XP
完全使用
unicode
开发,那为什么在
xp
下还会有乱码呢?
内码的存在,内码不兼容
unicode
。或者要解释的不是unicode,而当前不支持该编码。
2、
为什么有
UTF-8
、
16
、
32
?为什么说
UTF-8
是
unicode
的呢?
unicode
不都是
16
位的吗?
为了兼容现在的编码。
3、
codepage
是什么东西?为什么存在?
4、
什么是国际化、本地化?为什么国际化、本地化那么困难?
Locale
。举个简单的例子:不同地方的日期的显示格式不同。
5、
DBCS
是什么咚咚?它与
UTF-8
,
unicode
有什么联系?
UTF-8
是属于
unicode
规范的,而
DBCS
不是。
UTF-8
是不定字节的(从一字节到六字节),而
DBCS
是双字节的。
DBCS
与
ASCII
同时存在来处理远东的一些字符(结合
codepage
来使用,
GBK
与
Big5
的
range
就有交错的),而
UTF-8
是
unicode
规范的实现,它包含了所有的字符。从
Windows2K
开始,从
Windows
系统的底层实现,已经全面基于
Unicode
,同时仍保证完全兼容
ANSI/DBCS
程序。
以下是对我这一阶段学习的小结:
一、
什么是
unicode
?
Unicode provides a unique number for every character,
no matter what the platform,
no matter what the program,
no matter what the language.
历史上有两个组织想独立创立单一字符集,一个是国际标准化组织(
ISO
)的
ISO 10646
,另一个是由很多大企业(
Apple
、
Compaq
、
HP
、
IBM
、
Microsoft
、
Oracle
等)组成的协会组织的
unicode
。
1991
年前后,他们合并了双方的工作,统一了编码表。虽然这两个组织都还独立的存在,但是他们的标准是兼容的。
Unicode
协会公布的
Unicode
标准严密地包含了
ISO 10646-1
实现级别
3
的基本多语言面。在两个标准里所有的字符都在相同的位置并且有相同的名字。
Unicode
标准额外定义了许多与字符有关的语义符号学,一般而言是对于实现高质量的印刷出版系统的更好的参考。
Unicode
详细说明了绘制某些语言
(
比如阿拉伯语
)
表达形式的算法,处理双向文字
(
比如拉丁与希伯来文混合文字
)
的算法和排序与字符串比较所需的算法,以及其他许多东西。
另一方面
, ISO 10646
标准
,
就象广为人知的
ISO 8859
标准一样
,
只不过是一个简单的字符集表
.
它指定了一些与标准有关的术语
,
定义了一些编码的别名
,
并包括了规范说明
,
指定了怎样使用
UCS
连接其他
ISO
标准的实现
,
比如
ISO 6429
和
ISO 2022.
还有一些与
ISO
紧密相关的
,
比如
ISO 14651
是关于
UCS
字符串排序的
.
考虑到
Unicode
标准有一个易记的名字
,
且在任何好的书店里的
Addison-Wesley
里有
,
只花费
ISO
版本的一小部分
,
且包括更多的辅助信息
,
因而它成为使用广泛得多的参考也就不足为奇了
.
二、
UTF-8
、
16
、
32
UTF
:
Unicode Transformation Format
首先
UCS
(
Unicode Char Set
)和
Unicode
只是分配整数给字符的编码表
.
现在存在好几种将一串字符表示为一串字节的方法
.
最显而易见的两种方法是将
Unicode
文本存储为
2
个
或
4
个字节序列的串
.
这两种方法的正式名称分别为
UCS-2
(
UTF-16
)和
UCS-4
(
UTF-32
)
.
除非另外指定
,
否则大多数的字节都是这样的
(Bigendian convention).
将一个
ASCII
或
Latin-1
的文件转换成
UCS-2
只需简单地在每个
ASCII
字节前插入
0x00.
如果要转换成
UCS-4,
则必须在每个
ASCII
字节前插入三个
0x00.
在
Unix
下使用
UCS-2 (
或
UCS-4)
会导致非常严重的问题
.
用这些编码的字符串会包含一些特殊的字符
,
比如
'\0'
或
'/',
它们在
文件名和其他
C
库函数参数里都有特别的含义
.
另外
,
大多数使用
ASCII
文件的
UNIX
下的工具
,
如果不进行重大修改是无法读取
16
位的字符的
.
基于这些原因
,
在文件名
,
文本文件
,
环境变量等地方
, UCS-2
不适合作为
Unicode
的外部编码
.
在
ISO 10646-1 Annex R
和
RFC 2279
里定义的
UTF-8
编码没有这些问题
.
它是在
Unix
风格的操作系统下使用
Unicode
的明显的方法
.
UTF-8
看起来不像是
unicode
,它只是作为一种过渡形态存在,作为新旧编码之间交互的桥梁。虽然它是遵循
unicode
规范的,但它更像是
DBCS
的改善版,是一种
MBCS
(
multi-byte char set
)。显然这个世界上不可能很快就完全
unicode
,
UTF-8
还将会一直存在下去。
Window NT
操作系统的基本文本表示是
UTF-16
,
WCHAR
是其基本数据类型。
UTF-8
以字节为编码单元,没有字节序的问题。
UTF-16
以两个字节为编码单元,在解释一个
UTF-16
文本前,首先要弄清楚每个编码单元的字节序。
Unicode
规范使用
BOM
(
Byte Order Mark
)来标记字节顺序。在
UCS
编码中有一个叫做“
ZERO WIDTH NO-BREAK SPACE
”的字符,它的编码是
FEFF
。而
FFFE
在
UCS
中是不存在的字符。所以,如果接收到
FEFF
就表明这个字节流是
Big-Endian
的;如果是
FFFE
则是
little endian
。
UTF-8
不需要用
BOM
来表明字节序,但可以用
BOM
来表明编码方式。
FEFF
的
UTF-8
编码是
EF BB BF
。
以下就是
UTF-8
的模板
0x0000 - 0x007F
用一个字节表示
0xxxxxxx
0x0080 - 0x07FF
用两个字节表示
110xxxxx 10xxxxxx
0x0800 - 0xFFFF
用三个字节表示
1110xxxx 10xxxxxx 10xxxxxx
举个例子,如果你遇到了
11100110 10110001 10001001 01000001
这样的字节流,首先你看第一个字节以
1110
开头,即读
3
个字节并按模板提取得到
0110 110001 001001(
去除模板标志﹐再四字节四字节读即
0x6c49)
,查
unicode
编码表就是
"
汉
"
字
,
而最后一个以
0
开头就一定是一个字节了,
0x0041
,也就是
"A"
。
三、
字符集、字符编码、内码
字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。像
ASCII
、
GB2312
、
Big5
都是属于字符编码。当然
UTF-8
、
16
也是一种字符编码。而
unicode
则是一种规范。
GB2312
是大陆的字符编码标准,属于国家标准。它是与
ASCII
码兼容的。后来又有
GBK1.0
、
GB18030
等字符编码标准,这些都是向下兼容的,但横向不兼容!比如
GB2312
与
Big5
在很多编码上是重叠的,是不兼容的;
Unicode
与
GB
标准码也是不兼容的。中文操作系统的内码是
GBK
编码。
由于现有的大量程序和文档都采用乐某种特定语言的编码,例如
GBK
,
windows
不可能不支持现有代码,而全部采用
unicode
!这就是为什么
windows
使用了内码机制。为了支持更多的地方语言文字,
windows
还使用了
code page
机制以使
windows
能够更方便的适应不同地方的语言文字。
GBK
对应的
code page
是
CP936
,
windows
代码页只支持单字节和双字节编码的。
GB2312-80
,是中国大陆使用的国家标准,其中一共编码了
6763
个常用简体汉字。
Big5
,是台湾使用的编码标准,编码了中国台湾使用的繁体汉字,大概有
8
千多个。
HKSCS
,是中国香港使用的编码标准,字体也是繁体,但跟
Big5
有所不同。
四、
VC
中的
Unicode
编程
这个网上的资料有很多的,最重要的一个概念就是
T
,
W
,
_UNICODE
、
UNICODE
等。这个理解起来感觉简单很多,因为只要你在程序中都使用
Unicode
就好了。数据的传输、数据的保存、数据的使用、转化都使用
Unicode
(目前基本上都是使用
UTF-8
比较多吧)。当然了,这里肯定还是会有编码格式转化的问题的,比如输入的不是
Unicode
,输出的不能是
Unicode
等。但只要你在程序中都使用
Unicode
就解决问题了。是不是我想得太简单了?
上面这些东西,很多是我从网上摘抄下来的,也有少部分是我自己的理解。如果有什么不对的地方,敬请指教。如果有什么讲的不清楚的、或者需要讲一下的,请提出来。如果有什么希望能够一起讨论讨论的,欢迎给我发邮件或回帖讨论!