naotang的测试成长空间,记录工作中的问题,学习中的心得。 个人网站:www.naotang.com

字符、字节和编码理解

上一篇 / 下一篇  2008-01-16 16:32:30 / 个人分类:Web测试

51Testing软件测试网L,Q}8`P#d

1、字符编码的发展51Testing软件测试网}g;[%n^#}

*~.IXpN Kmr0从计算机对多国语言的支持角度看,大致可以分为三个阶段:51Testing软件测试网9\Kz+NtK

7Q.e&o] e%g i`0阶段一:ASCII51Testing软件测试网z2g3LU_i v { p2iR `%p
--计算机刚开始只支持英语,其它语言不能够在计算机上存储和显示。
6|R[{ I4U-v0--英文 DOS51Testing软件测试网o[JC+baE)K._&u

7eAb.G4S1W^o0阶段二
:ANSI编码(本地化)
&@*],As/a G8A0--为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符。比如:汉字 '中' 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储。不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用2个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。
RM3`sh2X~1i ~a0--中文 DOS,中文 Windows 95/98,日文 Windows 95/9851Testing软件测试网i9z5v1p;t+e\.ny7t

*]R%\%Cr*Z0阶段三
:UNICODE(国际化)51Testing软件测试网O Y6OPDm}}
--为了使国际间信息交流更加方便,国际组织制定了 UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。51Testing软件测试网 zaJ9Q @
--Windows NT/2000/XP,Linux,Java51Testing软件测试网&^GX8g?]7Gu{0M7bR7L

s{&Z"It%y0字符串在内存中的存放方法:

0N c s/Bg2r'c`\051Testing软件测试网PT0Z U$ii*V'l

在 ASCII 阶段,单字节字符串使用一个字节存放一个字符(SBCS)。比如,"Bob123" 在内存中为:51Testing软件测试网 U ? _??
42 6F 62 31 32 33 0051Testing软件测试网B0dU*^ s;L5V/D0p~
B o b 1 2 3 \0

M*gc"PmPSu"]051Testing软件测试网PN ?.M;W?q,{

在使用 ANSI 编码支持多种语言阶段,每个字符使用一个字节或多个字节来表示(MBCS),因此,这种方式存放的字符也被称作多字节字符。比如,"中文123" 在中文 Windows 95 内存中为7个字节,每个汉字占2个字节,每个英文和数字字符占1个字节:
4z%h?qS$v4Ht"[h&Lg0D6 D0 CE C4 31 32 33 0051Testing软件测试网)_?qO)X
中 文 1 2 3 \0

7o+d qXN0

r(g3SG1H"}+L0在 UNICODE 被采用之后,计算机存放字符串时,改为存放每个字符在 UNICODE 字符集中的序号。目前计算机一般使用 2 个字节(16 位)来存放一个序号(DBCS),因此,这种方式存放的字符也被称作宽字节字符。比如,字符串 "中文123" 在 Windows 2000 下,内存中实际存放的是 5 个序号:51Testing软件测试网_Qal|M ? ||%`
2D 4E 87 65 31 00 32 00 33 00 00 00      ← 在 x86 CPU 中,低字节在前51Testing软件测试网$bK3j*S:M!KmF&H-i
中 文 1 2 3 \0  
$S/_ [k$a5A0vi:j0一共占10个字节。51Testing软件测试网2tk;rf-uLm7B%`5j/^

51Testing软件测试网;f ]$V,\mU0U/gUE

2、字符,字节,字符串51Testing软件测试网cJ@}3s(\S yR)V

|]r.qU|a0理解编码的关键,是要把字符的概念和字节的概念理解准确。这两个概念容易混淆,我们在此做一下区分:51Testing软件测试网'B;e|x jY(q
字符 
(} @;|N r f"t|)YB0--人们使用的记号,抽象意义上的一个符号         51Testing软件测试网%E.hc:kCB,J9j%jx
--'1', '中', 'a', '$', '¥', ……51Testing软件测试网"t4RaT-H:|,Q9b^5t
51Testing软件测试网 KSDH-h:?uWO SQ
字节
{%t-Mo?5?&Nt0--
计算机中存储数据的单元,一个8位的二进制数,是一个很具体的存储空间 51Testing软件测试网(@NT~+[ wd
--0x01, 0x45, 0xFA, ……
aV.@5z-Zs\,x051Testing软件测试网(F^%J[!|zc
ANSI字符串
 
$W:f3f6y*y_!X@/l0--在内存中,如果“字符”是以 ANSI 编码形式存在的,一个字符可能使用一个字节或多个字节来表示,那么我们称这种字符串为 ANSI 字符串或者多字节字符串。51Testing软件测试网O7[ oT8uWf7tv
--"中文123"(占7字节)51Testing软件测试网~!X'GD {

3Ko;ttk)I8q0UNICODE字符串
 
g.EK#P+XU:P!a+u8C0--在内存中,如果“字符”是以在 UNICODE 中的序号存在的,那么我们称这种字符串为 UNICODE 字符串或者宽字节字符串。 
IU*LW/Nd1y4yY0--L"中文123"(占10字节)

Dnut? i0

$\ Ub.z[0由于不同 ANSI 编码所规定的标准是不相同的,因此,对于一个给定的多字节字符串,我们必须知道它采用的是哪一种编码规则,才能够知道它包含了哪些“字符”。而对于 UNICODE 字符串来说,不管在什么环境下,它所代表的“字符”内容总是不变的。51Testing软件测试网 BL/G{ { VT

5u/s8oAU[ t)h03、字符集与编码51Testing软件测试网 t7I*F'I,pj vk

7l$z"GRR+a5l1E%~)x)N-^0各个国家和地区所制定的不同 ANSI 编码标准中,都只规定了各自语言所需的“字符”。比如:汉字标准(GB2312)中没有规定韩国语字符怎样存储。这些 ANSI 编码标准所规定的内容包含两层含义:51Testing软件测试网?|B~.x&O*p

51Testing软件测试网(mJ#N(kp(C4^

使用哪些字符。也就是说哪些汉字,字母和符号会被收入标准中。所包含“字符”的集合就叫做“字符集”。51Testing软件测试网 z(o@@D4Zp2@`
规定每个“字符”分别用一个字节还是多个字节存储,用哪些字节来存储,这个规定就叫做“编码”。
%h|-h$EMB0各个国家和地区在制定编码标准的时候,“字符的集合”和“编码”一般都是同时制定的。因此,平常我们所说的“字符集”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”这层含义外,同时也包含了“编码”的含义。51Testing软件测试网 }_,D {q|

51Testing软件测试网m&@BmJ't

“UNICODE 字符集”包含了各种语言中使用到的所有“字符”。用来给 UNICODE 字符集编码的标准有很多种,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。51Testing软件测试网5|huxB yE

F6@5?;M1C3]0@l-[04、常用的编码简介51Testing软件测试网P*|*Iq(F/N L.| P
51Testing软件测试网P/AP$T{B+_)i
根据编码规则的特点,把所有的编码分成三类:51Testing软件测试网AlE1|9z;i

)w logo7Mm {$g$d'h*dR0单字节字符编码ISO-8859-1 
DJ?h FO]bF-]fB0--最简单的编码规则,每一个字节直接作为一个 UNICODE 字符。比如,[0xD6, 0xD0] 这两个字节,通过 iso-8859-1 转化为字符串时,将直接得到 [0x00D6, 0x00D0] 两个 UNICODE 字符,即 "ÖÐ"。反之,将 UNICODE 字符串通过 iso-8859-1 转化为字节串时,只能正常转化 0~255 范围的字符。51Testing软件测试网 k u@s|0B0C0b5~

1Y1V0W-lH'g0H g`0ANSI 编码
 GB2312,BIG5,Shift_JIS,ISO-8859-2 …… 
Dd;@v Ju[ ]E0--把 UNICODE 字符串通过 ANSI 编码转化为“字节串”时,根据各自编码的规定,一个 UNICODE 字符可能转化成一个字节或多个字节。反之,将字节串转化成字符串时,也可能多个字节转化成一个字符。比如,[0xD6, 0xD0] 这两个字节,通过 GB2312 转化为字符串时,将得到 [0x4E2D] 一个字符,即 '中' 字。51Testing软件测试网2h1_~6A3n&T
“ANSI 编码”的特点:
e1LX0QofY7D"Eg01. 这些“ANSI 编码标准”都只能处理各自语言范围之内的 UNICODE 字符。
r~)^ Oi nY)n02. “UNICODE 字符”与“转换出来的字节”之间的关系是人为规定的。51Testing软件测试网Njd7mY7i

*G(y5tU:H{ bH1`0UNICODE 编码 UTF-8,UTF-16,UnicodeBig …… 51Testing软件测试网k5\!IEuL
--与“ANSI 编码”类似的,把字符串通过 UNICODE 编码转化成“字节串”时,一个 UNICODE 字符可能转化成一个字节或多个字节。51Testing软件测试网~ ?[?4r8fB
与“ANSI 编码”不同的是:51Testing软件测试网%X SL\X X0^ds
1. 这些“UNICODE 编码”能够处理所有的 UNICODE 字符。
$i"]z~:j/{v}02. “UNICODE 字符”与“转换出来的字节”之间是可以通过计算得到的。

lrFzv n3G8Z/W9F0

y2bQ,~[/mFA2S:r|0我们实际上没有必要去深究每一种编码具体把某一个字符编码成了哪几个字节,我们只需要知道“编码”的概念就是把“字符”转化成“字节”就可以了。对于“UNICODE 编码”,由于它们是可以通过计算得到的,因此,在特殊的场合,我们可以去了解某一种“UNICODE 编码”是怎样的规则。51Testing软件测试网#bJpesqO5]J

51Testing软件测试网9G6P7l3]|EL4?nf

ASCII 码
n Y2~ @ L:Ym0
--------------------------------------------------------------------------
f lX'Ocz4Sa0 7 位(00~7F)。 32 ~ 127 表示字符。32 是空格, 32 以下是控制字符(不可见)。51Testing软件测试网'z&L2@o}Z
第8位没有被使用。全世界很多人同时对这个位的含义发展了不同的用处。比如 IBM PC 中的 OEM 字符集。51Testing软件测试网y)g]u@ \ Qr
最后就 128 位以下的用处达成共识,制定了 ASCII 标准。
L[0c%`]#EAy0而 128 位以上的可能有不同的解释,这些不同的解释就叫做 code pages.51Testing软件测试网Z8[w:DY pe
甚至有用于在同一台电脑上解释多种语言的 code page.51Testing软件测试网 l2X:n:x F1Re

&L)z#}R;~Tu0同时,在亚洲发生了更加疯狂的事情。亚洲语言的字符集通常数以千计, 8 位已经不足以表达,这通常用一种
%xw n.@ `'rkap)enxp0很凌乱的,叫做 DBCS(双字节字符集,double byte character set) 的系统来解决。
CS.||s Z0这种系统中,有些字符占用 1 字节,有些 2 字节。这样一来,在字符串中向前解析很容易,而倒退却很麻烦。51Testing软件测试网0Y-M8eqLx,? D;I(`K
程序员们被建议,不要使用 s++ 或 s-- 来前进和后退,而使用一些函数,比如 Windows 的 AnsiNext 和
V)~g1sQ7@H0AnsiPrev. 因为这些函数知道是怎么回事。51Testing软件测试网 y;Xl2Nbv(V~@

I#~$H1c|R1{ A0这些不同的假设(code page)在单个的机器上没有问题。而随着 Internet 的发展,字符串要从一个机器上移到
;\W d6O&I6_6k0另一个机器上,这就产生了问题。于是, Unicode 出现了。51Testing软件测试网.Su f[1F"E{4l

]_"m)c Z:|0Unicode
[{?m#] Z1m0N8N*b0--------------------------------------------------------------------
)f4p T]u9h0Unicode 是一个勇敢的成就。它把在这个星球上的每一个合理的文字系统整合成了一个单一的字符集。51Testing软件测试网.d:w Kn,F H;zn
很多人还存在这样的误解: Unicode 仅仅是 16 位的这么简单,每个字符占 16 位,所以一共有 65536 个可能的字符。51Testing软件测试网h;H1G-qk#i3JS
然而,这是错误的。不过不要紧,因为这是大部分人都会犯的一个普遍的错误。51Testing软件测试网JdZ3T(t8~"Ti1u,p/c

51Testing软件测试网W!P-`%r;? s:D#d|

实际上,Unicode 理解字符的方式是截然不同的,而这是我们必须了解的。
K3?i,O c,t0到目前为止,我们都曾经认为:一个字符对应到一些在磁盘上或内存中储存的位(bits). 如: A -> 0100 000151Testing软件测试网xK,u8r bxj&R#A+?
而在 Unicode 中, 一个字符实际上对应一种叫做 code point 的东西。51Testing软件测试网,oQ)@[PS"eI#i%M
比如 A 这个字符,是抽象的(原文:platonic,柏拉图式的,理想的)一个概念。
:[)EJ0h&v$_+v6j0无论是 Times New Roman 或者 Helvetica 或者其他的什么字体中,都代表同一个字符。但是它和小写的字母 a 不同。51Testing软件测试网 ^~ C6O*a
但是在其他的语言,比如希伯莱语(Hebrew) 或者德语(German), 阿拉伯语(Arabian) 中,同一个字母的不同的字形代表的含义是否
'U&Aw f&_p0相同,是有争议的。经过长时间的争论,这些也终于被确定了。

h#{j X9O*Rv0

$yX c$O5Q'X:x"xkU j0每一个字母表中的每一个抽象的字母,都被赋予了一个数字,比如 U+0645. 这个叫做 code point.
G|8Sf1n#K\0U+ 表示: Unicode, 数字是 16 进制的。51Testing软件测试网2Bp6W1Jf.e9e6Ak
你可以通过 charmap 命令来查看所有这些编码。(Windows 2000/XP 中). 或者访问 Unicode 的网站(http://www.unicode.org
&t ~Yr3~,]!y#Aq0Unicode 中 code point 的数字的大小是没有限制的,而且也早就超过了 65535. 所以不是每个字符都能存储在两个字节中。
[V R%ka;f0那么,一个字符串 "Hello", 在 Unicode 中会表示成 5 个 code points :51Testing软件测试网kGU[1q2V\)d
  U+0048 U+0065 U+006C U+006C U+006F
kS$r(O SDOG"h5a0只不过是一些数字。但我们现在还没有提到如何在磁盘或者 Email 中表示这些信息,这就是我们下面要提到的编码(Encoding) 干的事情。

f*e@-Yq+dn[9^051Testing软件测试网Fu KM.@+n-js

Encodings (编码)
(H]"wx3d w0-------------------------------------------------------------------------
oF p4V,s!Y+b0最初的 Unicode Encoding, 使用两个字节表示一个字符。那么 "Hello" 表示为:
_*bfY8AX)F$YZ0  00 48 00 65 00 6C 00 6C 00 6F
0P!W+@ GpG`0实际上,还有一种表示方式:
$SGW)M n6j+x9l0  48 00 65 00 6C 00 6C 00 6F 00
8yLt'CwRR!f0到底高位字节在前还是低位字节在前面,是两种不同的模式。这要看特定的 CPU 在何种模式下工作的更快。 所以这两种都有。
)`qV/e}6~.~0这就有了两种不同的 Unicode 表示方式了,为了区分,人们又采用了一种奇异的方式:
'jA0UI? i6S+V0在每一个 Unicode 字符串的前面,加上 FEFF (这称为 Unicode 字节顺序标志,Unicode Byte Order Mark).51Testing软件测试网L0U AA]A!@q
如果你交换高位和低位次序,那么会加上一个 FFFE. 这样,读这个字符串的人才知道要对每两个相邻的字节进行交换。51Testing软件测试网&j(`lFg EE
但在最初的时候,并不是每一个 Unicode 字符串都有这个标志的。51Testing软件测试网h2M,fk4p$@:GW;[-T w

@g{TbQ8Z0这看起来很不错。可程序员们开始抱怨了,“看看那些零!”。因为有些是美国人,他们使用英语。而英语中很少需要使用 U+00FF 以上的51Testing软件测试网hO y#P#gp
字符, 有些人无法忍受采用双倍的存储空间来存储每个字符。
,?:_DL(@+b:SD0基于这些原因,很多人决定忽视 Unicode, 而同时,事情变得更糟了。51Testing软件测试网0]2h{ sh/z/^']

M AUuRN"iED0然后人们制定了 UTF-8. UTF-8 是用于保存 Unicode code points 的另一套系统。51Testing软件测试网+e?1h:m2n*]OZ)Xj-nM
每一个 U+ 数字,在内存中占用 8 bit. 在 UTF-8 中,任何一个 0~127 的 code point 占用一个字节。51Testing软件测试网'r6B%kPB&H| Q
只有 128 以及更大的才占用 2, 3, 直到 6 个字节。51Testing软件测试网F,i&\N9E)\^\
具体如下图所示:51Testing软件测试网'^Z7|-d.M7Pp!`/U)S#a

0`Q,Qh e*~;{/G016进制的最小的数    16进制的最大的数   内存中的字节序列
Lm#H*p-\Lj!j nE Z0------------------------------------------------------------------------------
;TZs"m!X xeb)j000000000          0000007F         0vvvvvvv51Testing软件测试网4A![wq#^X
00000080          000007FF         110vvvvv 10vvvvvv
NX/|Fp`Jv_E000000800          0000FFFF         1110vvvv 10vvvvvv 10vvvvvv
e {V.T{l| S5{000010000          001FFFFF         11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
cuetx k1e;l000200000          03FFFFFF         111110vv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv51Testing软件测试网 Vd?2\mb(p
04000000          7FFFFFFF         1111110v 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv 10vvvvvv

+D G/Hp Z/K0

`HSA sBZ${0这看起来很不错,其中的英文字符和 ASCII 中一样。所以美国人根本没意识到有什么错误。只有世界上的其他国家需要使用高位的字节。
D2qLti"e2y\0特别的,"Hello" 这个字符串,Unicode code point 为 U+0048 U+0065 U+006C U+006C U+006F, 会被存储为 48 65 6C 6C 6F。
$KB cl3Z G1I0和 ASCII, ANSI, 以及在这个星球上的任何一个 OEM 的字符集中表示的含义都一样。51Testing软件测试网x6efn&cy
现在,如果你需要表示重音的字符,或者希腊语,你需要使用多个字节来表示一个 code point. 但美国人不会介意这些。51Testing软件测试网&y rF&v)L(I2\*vi
(UTF-8 还有一个好处就是,老的字符串处理程序使用一个为 0 的字节来表示 null-terminator, 不会截断字符串)

W4X*dG3@*m5a;N051Testing软件测试网o2e~J#O+SzB

到目前为止已经介绍了三种 Unicode 的表示方法:

-zQ ^1_4Tp@a-o i051Testing软件测试网"qVc#Cjmza

传统的双字节表示方法, 称为 UCS-2(因为有 2 个字节) 或者 UTF-16(因为有 16 个位)
E3T(J9E,Wz0而且你还要搞清楚是高位在前的,还是高位在后的 UCS-2.

E5gg?c3o`0

t3V R ^{+@0还有一种就是新的 UTF-8. 如果你的程序只使用英文的话,它仍然会工作正常。

Ka.K l6Gh0

*G2_i a,c:Kq0实际上还有一堆的其他办法对 Unicode 进行编码:51Testing软件测试网'Uxnx7t"rH-sS
有 UTF-7,这种编码方式大部分和 UTF-8 相同,但保证高位一定为 0.
6^Ph4xb.D0所以如果你必须通过某种 Email 系统传送 Unicode,这些系统认为 7 位足够了,那使用 UTF-7 会正常。51Testing软件测试网J9XI.}],q
还有 UCS-4, 储存每一个 code point 为 4 个字节。它的优点是每一个字符都保存为同样长的。但很明显,缺点是浪费太多存储空间了。51Testing软件测试网&Kd#[eF9aY%`5D

51Testing软件测试网 hip8u.G)c*Zrq:T b`

所以,现在你思考问题要把每一个字符想象成抽象的一个 unicode code point. 而它们同样可以使用任何旧的方式编码。51Testing软件测试网-e Mhv5q`'m%Y
举例来说,你可以把 Unicode 字符串 Hello (U+0048 U+0065 U+006C U+006C U+006F) 编码(encode)为
hc$O#?w+bm*N0ASCII, 或者古老的 OEM 希腊语编码,或者希柏莱 ANSI 编码,等等。而有些字符串不能显示!
&H%uapsg-l0也就是说,假如你要表示一个在某个编码中没有对应的 Unicode code point, 通常会显示为一个 ? 或者一个白色的小方框。51Testing软件测试网t R]!_ oL |.b

QfD/j)Vfo0英文常用的一些编码有, Windows-1252(Windows 9x 标准 for 西欧语言)51Testing软件测试网d4X,C(h2hk"Q!MH8e
以及 ISO-8859-1, aka Latin-1(对任何西欧语言也有效)
NrT:g~-Ai2l0如果用这些编码来尝试存储俄文字符,你会得到一堆的 ?

o,LG)?c$}*E051Testing软件测试网E$d4@4fR

UTF 7, 8, 16 以及 32 都有一个优点,能够正确的存储任何的 code point.

{$Av ^(Qz0

x8@+?W#G G0最简单,也是最重要的几个概念
hWT4`~n0====================================================================51Testing软件测试网R ](X+pDZ _ {
一个字符串不指定它使用什么编码是没有意义的。51Testing软件测试网`3[Nwz
再也不要假定, “纯”文本(plain text) 是 ASCII.
:_&oEuUb0没有 “纯文本” 这个东西。

/a)IF@z0

{*o,sL+`uPd0如果你有一个字符串,在内存中,在文件中,或者在 Email 消息里,你必须知道它的编码是什么。否则你无法正确的解释或者显示给用户。51Testing软件测试网 L t2\n1b#W
所有的诸如 “我的网页不能正常显示了”,或者 ”Email 消息不能正常显示了“ 之类的愚蠢问题, 都是因为, 没有告诉你到底是使用的那种编码,51Testing软件测试网(b!ihkviq3l
UTF-8 还是 ASCII 还是 ISO 8859-1 或者 Windows 1252 ?? 那么自然无法正常的解释和显示,甚至不知道字符串该在哪里结束。

pF$H{zL2]j0X0

/{(t eM5f%pV0那么如何保留这样的编码标志,来表示字符串的编码? 有一些基本的办法。
*iRZ C#_(u8qIHM0比如对于 Email 来说,在表单的 header 中加上:51Testing软件测试网.HJ S:}*{eZ(` Qv

51Testing软件测试网fY-M)k/@

Content-Type:text/plain;charset="UTF-8"

_8na{,]u-j%V0

!X1zEl0~G0对于 Web 页面来说,原来的做法是, Web 服务器随着 web 页面本身一起,发送一个类似于 Content-Type 的 http header.51Testing软件测试网Y5]#@.lJ
(不是在 HTML 里面,而是作为一个 response header 在 HTML 页之前发送)

T ~bnv(Es7}&N051Testing软件测试网!K&oo(I*~y8K

这样做有一个问题。如果你的 Web 服务器同时有多个站点,站点由多个不同的人用不同的语言开发的程序混在一起。那么 Web 服务器将无从得知,
D]9QNm J~U0每一个文件是用什么编码方式写的。这样也就无法发送正确的 Content-Type header.
&Fv+t"@;Eph0如果你能够在每一个 HTML 文件中记录 Content-Type 信息,那么就很方便了。可这念头似乎也很疯狂,因为你还没有知道用什么编码方式去
-jHrLz!E0读取这个文件,又怎么能读出编码信息呢?51Testing软件测试网m%o A)r;hB XTj
幸好,几乎每一种编码中,对 32~127 的字符都解释的相同。所以你可以在每一个 html 文件中这么写:51Testing软件测试网S0U/P E^g y2?;Z

51Testing软件测试网:?hGGZN*V

<html>51Testing软件测试网\VHG*Dj0z"k
<head>
-c5`9nW7k0<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

%H6Pi\k~0

.oA8zU:E,f#p$bh Z0但是要注意, 这个 meta 标签必须放在 head 中靠前面的位置才能保证不会出问题。 因为 Web 服务器读到这里的时候,就会停止解析,
8Q#~,Y K&_5b#e8d0然后用读到的这个编码方式重新解析页面。51Testing软件测试网S(QM%^*k0g

51Testing软件测试网-v2J$oi+O;GG

那么,作为 Web 浏览器来说,如果没有在 meta 标签中或者 http headers 中发现 Content-Type, 会怎么样呢?51Testing软件测试网;kB3a"tG%HE
IE 是这么做的:
7q\\2N{6x$s7D~@Se0先尝试去猜,根据特定的字节出现在各种语言的典型的编码中的频率。51Testing软件测试网HT b.r%T d8bjlg
如果编码设定不正常,用户可以通过 View|Encoding 菜单来尝试不同的编码方式。(当然,不是每个人都知道该这样做)51Testing软件测试网4A(PQ b4O%w|

51Testing软件测试网 iP%}6P\%o.aj t

在 VB, COM, Windows NT/2000/XP 中,默认的字符串类型是 UCS-2(2字节)的。51Testing软件测试网aT A!YC/oC5r
在 C++ 代码中, 我们可以定义字符串为 wchar_t(wide char),同时用 wcs 系列的函数代替 str 系列的函数。
sYF"ZPM-\0如 wcscat, wcslen, 而不是 strcat, strlen.51Testing软件测试网]5R&}F@.}
在 C 代码中,要创建 UCS-2 字符串的话,只要在前面加一个 "L", 如 L"Hello"

#fPr n)n+V051Testing软件测试网:]l&I A _*h3H!^u

对于 Web 页面,最好统一为使用 UTF-8 编码。 这个编码已经被各种 web 浏览器支持了很多年了。

MVJu8}Lv7p051Testing软件测试网Y*GL,_y/RJ G;n5h d

5、程序中的字符与字节51Testing软件测试网e-A&bP8Q.u`q8iy

@ [(R7G"h3_:~-U0
在 C++ 和 Java 中,用来代表“字符”和“字节”的数据类型,以及进行编码的方法:51Testing软件测试网3j _H g5|:u%x

51Testing软件测试网,X{$UU2p#F)~`

类型或操作     C++          Java
,IL+r*lO(D0字符          wchar_t       char51Testing软件测试网y;`2Ua2kbj
字节          char          byte
@8M:U oW'tc#Y i0ANSI字符串    char[]        byte[]51Testing软件测试网0ua0l*]CuY
UNICODE字符串 wchar_t[] String
!f*x.Ff{:r0字节串→字符串   mbstowcs(), MultiByteToWideChar() string = new String(bytes, "encoding")
ju6y sh0a)P0字符串→字节串   wcstombs(), WideCharToMultiByte() bytes = string.getBytes("encoding")51Testing软件测试网_P[q"?GF
51Testing软件测试网1j'O4J%c,hOpN7x9A
以上需要注意几点:
J:b!g8x'G]1x01.Java 中的 char 代表一个“UNICODE 字符(宽字节字符)”,而 C++ 中的 char 代表一个字节。
#zQs%kq0~3P*`02.MultiByteToWideChar() 和 WideCharToMultiByte() 是 Windows API 函数。51Testing软件测试网+j-u#u7DY+t


TAG: 编码 unicode 字节 ASCII ANSI 字符 Web测试

 

评分:0

我来说两句

Open Toolbar