Python 学习之进制与编码

                            进制

日常生活中,我们最熟悉的数据就是十进制计数。它的数值部分由十个不同的数字符号0、1、2、3、4、5、6、7、8、9来表示,我们把这些数字符号叫做数码,表示十种不同的状态。数码处于不同的位置(或数位)代表的意义是不同的。
二进制数的含义
二进制数的每个数位只可能取两个不同的数码"0"和"1",而且是"逢二进一"。为了熟悉二进制数的表示,我们就几个简单的数字,列出二进制数与其对应的十进制数。
正如十进制数据中最大的数码是9一样,在二进制数据中最大的数码是1。也就是说,在二进制数数据中,不能出现2或者比2大的数码;否则就是错误的数据。这一点初学者尤其应该注意。
八进制数的表示
八进制数的基数为8,具有八个数码,逢八进一,计数如下:
0,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20,21,22,23,24,25,26,27,30,31,32,33……
十六进制数的表示
十六进制数的基数为16,具有16个数码,逢16进一,计数如下:
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10,11,12,13,14,15,16,17,18,19,1A,1B…… 进制转换 要把一个十进制数转换为二进制数,首先把这个数以小数点为界分为两部分。对于整数部分是对该数除以2,记下它的余数,如果其商不等于0,再对其商除以2,仍然记下余数,重复此过程,直到商为零为止。倒序(先出来的余数写在最右边,依次类推,最后的余数写在最左边)写下所有余数,这个由余数构成的序列就是这个整数对应的二进制数;对于小数部分,则需要对该小数乘以2,记下它的整数部分,去掉整数部分后,如果余下的小数部分不为零,再对小数部分乘以2,再记下其整数部分,重复此过程,直到小数部分为零为止。顺次记下每次的整数部分就是这个数小数部分的二进制结果。
把该数整数部分的二进制结果和小数部分的二进制结果组合起来就是这个数据对应的二进制结果。
值得注意的是:并不是所有的有限位十进制数都能转换成有限位二进制数,对于这种情况,根据精度要求,保留一定的精度就可以了。
在计算机内部所有的信息都以二进制的形式进行存放、处理与传送,但在书写时可以以八进制和十六进制表示,这是因为二进制与八进制和十六进制之间的转换是很方便的。
由于十六进制的基数是16,八进制的基数是8,将十六进制数和八进制数转换为十进制和对二进制数求大小的方法相同,仍然采用将各数码乘以该位的权值,然后再取和的方法。
下面我们看简单数据的各种进制之间的转换关系:
(1)十六进制、八进制数与二进制数的直接转换
由于2的四次幂是16,2的三次幂是8,因此一位16进制数对应与四位二进制,一位八进制数对应三位二进制数。
为了将二进制数转化为十六进制数,只需从小数点开始向前,每四位一组划开,再从小数点向后,也是每四位一组划开,若小数点右边的最后一组不够四位,则添0补足四位,然后可以从上表中查到每一组对应的16进制数,依次写出来就可以了。同样的方法,若要将二进制数转化为八进制数,只需从小数点开始向前,每三位一组划开,再从小数点向后,也是每三位一组划开,若小数点右边的最后一组不够三位,则添0补足三位,然后从上表中查到每一组对应的八进制数,依次写出来就行了。

如果要将八进制数转换为二进制,则只要把每个八进制位用相应的三位二进制数代替。 当然,对于上表中不够三位的数据,前边以0补足。例如:八进制的1要变成001,八进制的2要变成010,等等。同理,如果要将十六进制数转换为二进制,则只要将每个十六进制位用相应的四位二进制数代替,对于上表中不够四位的数据,也是在前边以0补足。例如,16进制的1要转换为0001,16进制的2要转换为0010,等等。
由此可见,八进制或十六进制数与二进制数之间的转换极为方便,而且用八进制或者十六进制书写数据要比二进制简短,口读也方便。因此八进制或十六进制数常用于指令的书写、手编程序或者目标程序的输入、输出。特别指出的是:计算机数据的存储和传输基本上以字节为单位,一个字节包含8个二进制位,正好是两位十六进制数,因此十六进制数在计算机的程序开发和内存管理程序中得到了极为广泛的应用。
在计算机界,为了标志不同数制的数据,一般在数据末尾使用特殊的标记。以D或不标记表示十进制数据,以B表示二进制数据,以H表示十六进制数据,以O表示八进制数据。例如:18H,则表示十六进制数据18,其等价于十进制数据24。17O则表示八进制的数据17,其值等价于十进制数15。

进制生活小应用

硬盘空间少比买的时候要少,

是因为换算时他们将 1024 按照 1000来算

500G的硬盘: Bytes:按1000来算

500G 硬盘
1K = 1000B
1M = 1000K
1G = 1000M = 1000*1000*1000B =100

500000000000/1024/1024/1024 B = 465.66128730773926 B

百兆宽带,下载速度只能达到十多兆。

宽带运营商按照二进制来计算,所以要100M的宽带要除8才是下载的速度。

 32位和64位 /32bit和64bit的区别

1.  对操作系统来说,64位和32位指最大内存寻址空间,32位最大4GB(2^32),64位理论上16EB(2^64),但现在一般都是2^48

2、对硬件来说,64位和32位指数据宽度,64位一次取8字节y也就是64bit,32取4字节也就是32bit,所以理论上64位比32位性能提高了一倍。

实际上的情况是,达不到,内存变大了,需要寻址更多。

3、对应用程序来说,应用程序基于操作系统 和硬件,其使用的指令宽度随系统和硬件变化。

32位和64位区别的最常见表现就是64万位操作系统可以支持4G以上的内存。缺点也是内存占用,64位代码比32位代码多占用空间,

现在来看64位操作系统兼容32位软件。反之则不行。

32位和64位最本质的区别是CPU来决定的,操作系统的位数是是看最大能把CPU的性能发挥到多高。我们现在在市面上见到的CPU都是64位的,32位的CPU已经是老古董了。


 

编码

  计算机编码指电脑内部代表字母或数字的方式.常见的编码方式有:ASCII编码,GB2312编码(简体中文),GBK,BIG5编码(繁体中文),ANSI编码,unicode,utf-8编码等
计算机编码,指电脑内部代表字母或数字的方式。

编码单位

  最小的单元是位(bit),接着是字节(Byte),一个字节=8位,英语表示是1 byte=8 bits 。机器语言的单位Byte。

  位 bit (比特)(Binary Digits):存放一位二进制数,即 0 或 1,最小的存储单位。

  字节 byte:8个二进制位为一个字节(B),最常用的单位。
  1B(bytes) = 8bit
  1KB (Kilobyte 千字节)=1024B, 
  1MB (Megabyte 兆字节 简称“兆”)=1024KB,
  1GB (Gigabyte 吉字节 又称“千兆”)=1024MB,
  1TB(Trillionbyte 万亿字节 太字节)=1024GB,
  1PB(Petabyte 千万亿字节 拍字节)=1024TB,
  1EB(Exabyte 百亿亿字节 艾字节)=1024PB,
  1ZB (Zettabyte 十万亿亿字节 泽字节)= 1024 EB,
  1YB (Yottabyte 一亿亿亿字节 尧字节)= 1024 ZB,
  1BB (Brontobyte 一千亿亿亿字节)= 1024 YB

 

进制

二进制数由0和1,八进制数由0-7, 十进制数由0-9,十六进制数由0-9,A,B,C,D,E,F组成,他们关系如下:
Binary(2)
Octal(8)
Decimal(10)
Hex(16)
0
0
0
00
1
1
1
1
10
2
2
2
11
3
3
3
100
4
4
4
101
5
5
5
110
6
6
6
111
7
7
7
1000
10
8
8
1001
11
9
9
1010
12
10
A
1011
13
11
B
1100
14
12
C
1101
15
13
D
1110
16
14
E
1111
17
15
F
 

上层字符

  字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。

编码分类

 

ASCII

  ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是基于罗马字母表的一套电脑编码系统,它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO 646。
  包含内容:
  控制字符:回车键、退格、换行键等。
  显示字符:英文大小写字符、阿拉伯数字和西文符号
  ASCII扩展字符集扩展:表格符号、计算符号、希腊字母和特殊的拉丁符号。
  0~31号及第127号(共33个)是控制字符或通讯专用字符,如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BEL(振铃)等;通讯专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等;
第32~126号(共94个)是字符,其中第48~57号为0~9十个阿拉伯数字;65~90号为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。
     在计算机的存储单元中,一个ASCII码值占一个字节(8个二进制位),其最高位(b7)用奇偶校验位。所谓奇偶校验,是指在代码传送过程中用来检验是否出现错误的一种方法,一般分奇校验和偶校验两种。奇校验规定:正确的代码一个字节中1的个数必须是奇数,若非奇数,则在最高位b7添1;偶校验规定:正确的代码一个字节中1的个数必须是偶数,若非偶数,则在最高位b7添1。
八进制
十六进制
十进制
字符
八进制
十六进制
十进制
字符
0
0
0
nul
100
40
64
@
1
1
1
soh
101
41
65
A
2
2
2
stx
102
42
66
B
3
3
3
etx
103
43
67
C
4
4
4
eot
104
44
68
D
5
5
5
enq
105
45
69
E
6
6
6
ack
106
46
70
F
7
7
7
bel
107
47
71
G
10
8
8
bs
110
48
72
H
11
9
9
ht
111
49
73
I
12
0a
10
nl
112
4a
74
J
13
0b
11
vt
113
4b
75
K
14
0c
12
ff
114
4c
76
L
15
0d
13
er
115
4d
77
M
16
0e
14
so
116
4e
78
N
17
0f
15
si
117
4f
79
O
20
10
16
dle
120
50
80
P
21
11
17
dc1
121
51
81
Q
22
12
18
dc2
122
52
82
R
23
13
19
dc3
123
53
83
S
24
14
20
dc4
124
54
84
T
25
15
21
nak
125
55
85
U
26
16
22
syn
126
56
86
V
27
17
23
etb
127
57
87
W
30
18
24
can
130
58
88
X
31
19
25
em
131
59
89
Y
32
1a
26
sub
132
5a
90
Z
33
1b
27
esc
133
5b
91
[
34
1c
28
fs
134
5c
92
\
35
1d
29
gs
135
5d
93
]
36
1e
30
re
136
5e
94
^
37
1f
31
us
137
5f
95
_
40
20
32
sp
140
60
96
'
41
21
33
!
141
61
97
a
42
22
34
"
142
62
98
b
43
23
35
#
143
63
99
c
44
24
36
$
144
64
100
d
45
25
37
%
145
65
101
e
46
26
38
&
146
66
102
f
47
27
39
`
147
67
103
g
50
28
40
(
150
68
104
h
51
29
41
)
151
69
105
i
52
2a
42
*
152
6a
106
j
53
2b
43
+
153
6b
107
k
54
2c
44
,
154
6c
108
l
55
2d
45
-
155
6d
109
m
56
2e
46
.
156
6e
110
n
57
2f
47
/
157
6f
111
o
60
30
48
0
160
70
112
p
61
31
49
1
161
71
113
q
62
32
50
2
162
72
114
r
63
33
51
3
163
73
115
s
64
34
52
4
164
74
116
t
65
35
53
5
165
75
117
u
66
36
54
6
166
76
118
v
67
37
55
7
167
77
119
w
70
38
56
8
170
78
120
x
71
39
57
9
171
79
121
y
72
3a
58
:
172
7a
122
z
73
3b
59
;
173
7b
123
{
74
3c
60
<
174
7c
124
|
75
3d
61
=
175
7d
125
}
76
3e
62
>
176
7e
126
~
77
3f
63
?
177
7f
127
del
 
 

GB2312

  GB2312又称为GB2312-80字符集,全称为《信息交换用汉字编码字符集·基本集》,由原中国国家标准总局发布,1981年5月1日实施,是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率,基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。
  GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。其中包括6763个汉字,其中一级汉字3755个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。
GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。
它是用双字节表示的,两个字节中前面的字节为第一字节,后面的字节为第二字节。习惯上称第一字节为“高字节” ,而称第二字节为“低字节”。“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0),“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。
以GB2312字符集的第一个汉字“啊”字为例,它的区号16,位号01,则区位码是1601,在大多数计算机程序中,高字节和低字节分别加0xA0得到程序的汉字处理编码0xB0A1。计算公式是:0xB0=0xA0+16, 0xA1=0xA0+1。

GBK

  GBK字符集是GB2312的扩展(K),GBK1.0收录了21886个符号,它分为汉字区和图形符号区,汉字区包括21003个字符。
  GBK字符集主要扩展了繁体中文字的支持。

BIG5

  BIG5又称大五码或五大码,1984年由台湾财团法人信息工业策进会和五间软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大众 (FIC)创立,故称大五码。
Big5码的产生,是因为当时台湾不同厂商各自推出不同的编码,如倚天码、IBM PS55、王安码等,彼此不能兼容;另一方面,台湾政府当时尚未推出官方的汉字编码,而中国大陆的GB2312编码亦未有收录繁体中文字。
Big5字符集共收录13,053个中文字,该字符集在中国台湾使用。耐人寻味的是该字符集重复地收录了两个相同的字:“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。
Big5码使用了双字节储存方法,以两个字节来编码一个字。第一个字节称为“高位字节”,第二个字节称为“低位字节”。高位字节的编码范围0xA1-0xF9,低位字节的编码范围0x40-0x7E及0xA1-0xFE。
尽管Big5码内包含一万多个字符,但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字,没有包含日文平假名及片假字母。例如台湾视“着”为“著”的异体字,故没有收录“着”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中。
 

GB18030

  GB18030的全称是GB18030-2000《信息交换用汉字编码字符及基本集的扩充》是我国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场上发布的软件必须符合本标准。GB 18030字符集标准的出台经过广泛参与和论证,来自国内外知名信息技术行业的公司,信息产业部和原国家质量技术监督局联合实施。
GB 18030字符集标准解决汉字、日文假名、朝鲜语和中国少数名族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位,收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容,填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准(GB2312,GB13000.1)兼容。
编码方法:
  GB 18030标准采用单字节、双字节和四字节三种方式对字符编码。
单字节部分使用0×00至0×7F码(对应于ASCII码的相应码)。
双字节部分,首字节码从0×81至0×FE,尾字节码位分别是0×40至0×7E和0×80至0×FE。
四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀,这样扩充的四字节编码,其范围为0×81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE,第二、四个字节编码码位均为0×30至0×39。
按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集(DBCS)。
接着是国际通用的unicode字符集
 

ANSI编码

  不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。

Unicode

  Unicode字符集编码是(Universal Multiple-Octet Coded Character Set) 通用多八位编码字符集的简称,支持世界上超过650种语言的国际字符集。Unicode允许在同一服务器上混合使用不同语言组的不同语言。它是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发,1994年正式公布,最新版本是2005年3月31日的Unicode 4.1.0。Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
编码方法
Unicode 标准始终使用十六进制数字,而且在书写时在前面加上前缀“U+”,例如字母“A”的编码为 0X0041 。所以“A”的编码书写为“U+0041”。
 

UTF-8 编码

  UTF-8是Unicode的其中一个使用方式。 UTF是 Unicode Translation Format,即把Unicode转做某种格式的意思。
  UTF-8便于不同的计算机之间使用网络传输不同语言和编码的文字,使得双字节的Unicode能够在现存的处理单字节的系统上正确传输。
  UTF-8使用可变长度字节来储存 Unicode字符,例如ASCII字母继续使用1字节储存,重音文字、希腊字母或西里尔字母等使用2字节来储存,而常用的汉字就要使用3字节。辅助平面字符则使用4字节。
 

UTF-16 和 UTF-32 编码

  UTF-32、UTF-16和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案,UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码;UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数
通过一个问题了解unicode编码
问题:使用Windows记事本的“另存为”,可以在ANSI、GBK、Unicode、Unicode big endian和UTF-8这几种编码方式间相互转换。同样是txt文件,Windows怎样识别编码方式的呢?
Unicode、Unicode big endian和UTF-8编码的txt文件的开头会多出几个字节,分别是FFFE(Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)。但这些标记是基于什么标准呢?
ANSI字符集定义:ASCII字符集,以及由此派生并兼容的字符集,如:GB2312,正式的名称为MBCS(Multi-Byte Chactacter System,多字节字符系统),通常也称为ANSI字符集。
UNICODE 与 UTF8、UTF16
由于每种语言都制定了自己的字符集,导致最后存在的各种字符集实在太多,在国际交流中要经常转换字符集非常不便。因此,产生了Unicode字符集,它固定使用16 bits(两个字节)来表示一个字符,共可以表示65536个字符
标准的 Unicode 称为UTF-16(UTF:UCS Transformation Format )。后来为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8,使用类似MBCS的方式对Unicode进行编码。(Unicode字符集有多种编码形式)
例如"连通"两个字的Unicode标准编码UTF-16 (big endian)为:DE 8F 1A 90
而其UTF-8编码为:E8 BF 9E E9 80 9A
当一个软件打开一个文本时,它要做的第一件事是决定这个文本究竟是使用哪种字符集的哪种编码保存的。软件一般采用三种方式来决定文本的字符集和编码:
检测文件头标识,提示用户选择,根据一定的规则猜测
最标准的途径是检测文本最开头的几个字节,开头字节 Charset/encoding,如下:
EF BB BF : UTF-8
FF FE : UTF-16/UCS-2, little endian
FE FF : UTF-16/UCS-2, big endian
FF FE 00 00 : UTF-32/UCS-4, little endian.
00 00 FE FF : UTF-32/UCS-4, big-endian.
  1、big endian和little endian
big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian。还是将49写在前面,就是little endian。
“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Litte-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。
我们一般将endian翻译成“字节序”,将big endian和little endian称作“大尾”和“小尾”。
  2、字符编码、内码,顺带介绍汉字编码
字符必须编码后才能被计算机处理。计算机使用的缺省编码方式就是计算机的内码。早期的计算机使用7位的ASCII编码,为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
GB2312(1980年)一共收录了7445个字符,包括6763个汉字和682个其它符号。汉字区的内码范围高字节从B0-F7,低字节从A1-FE,占用的码位是72*94=6768。其中有5个空位是D7FA-D7FE。
GB2312支持的汉字太少。1995年的汉字扩展规范GBK1.0收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。2000年的GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。PC平台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。
从ASCII、GB2312、GBK到GB18030,这些编码方法是向下兼容的,即同一个字符在这些方案中总是有相同的编码,后面的标准支持更多的字符。在这些编码中,英文和中文可以统一地处理。区分中文编码的方法是高字节的最高位不为0。按照程序员的称呼,GB2312、GBK到GB18030都属于双字节字符集 (DBCS)。
有的中文Windows的缺省内码还是GBK,可以通过GB18030升级包升级到GB18030。不过GB18030相对GBK增加的字符,普通人是很难用到的,通常我们还是用GBK指代中文Windows内码。
GB2312的原文还是区位码,从区位码到内码,需要在高字节和低字节上分别加上A0。
在DBCS中,GB内码的存储格式始终是big endian,即高位在前。
GB2312的两个字节的最高位都是1。但符合这个条件的码位只有128*128=16384个。所以GBK和GB18030的低字节最高位都可能不是1。不过这不影响DBCS字符流的解析:在读取DBCS字符流时,只要遇到高位为1的字节,就可以将下两个字节作为一个双字节编码,而不用管低字节的高位是什么。
  3、Unicode、UCS和UTF(UCS Transformation Format)
前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容),与GB码不兼容。例如“汉”字的Unicode编码是6C49,而GB码是BABA。
UCS规定了怎么用多个字节表示各种文字。而怎样传输这些编码,是由UTF(UCS Transformation Format)规范规定的。
常见的UTF规范包括UTF-8、UTF-7、UTF-16。
  4、UTF的字节序和BOM
UTF-8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?
Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:
  在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。
这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF(读者可以用我们前面介绍的编码方法验证一下)。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
Windows就是使用BOM来标记文本文件的编码方式的。
  扩展的ASCII字符集采用8bit255个字符显然不够用,于是各个国家纷纷制定了自己的文字编码规范,其中中文的文字编码规范叫做“GB2312-80”(就是GB2312),它是和ASCII兼容的一种编码规范,其实就是用扩展ASCII没有真正标准化这一点,把一个中文字符用两个扩展ASCII字符来表示。文中说的的中文ASCII码实际上就是简体中文的编码2312GB!它把ASCII又扩充了一个字节,由于高位的第一位是0,所以会出现负数的形式,url编码就是将汉字的这个GB2312编码转化成UTF-8的编码并且每8位即一个字节前面加上%符号表示。
  那为何UTF-8是进行网络的规范传输编码呢?
  Unicode里,所有的字符被一视同仁。汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”,注意,汉字是“一个字符”了,于是,拆字、统计字数这些问题也就自然而然的解决了。但是,这个世界不是理想的,不可能在一夜之间所有的系统都使用Unicode来处理字符,所以Unicode在诞生之日,就必须考虑一个严峻的问题:和ASCII字符集之间的不兼容问题。
我们知道,ASCII字符是单个字节的,比如“A”的ASCII是65。而Unicode是双字节的,比如“A”的Unicode是0065,这就造成了一个非常大的问题:以前处理ASCII的那套机制不能被用来处理Unicode了
另一个更加严重的问题是,C语言使用’\0’作为字符串结尾,而Unicode里恰恰有很多字符都有一个字节为0,这样一来,C语言的字符串函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉
于是,比Unicode更伟大的东东诞生了,之所以说它更伟大是因为它让Unicode不再存在于纸上,而是真实的存在于我们大家的电脑中。那就是:UTF
UTF= UCS Transformation Format UCS转换格式,它是将Unicode编码规则和计算机的实际编码对应起来的一个规则。现在流行的UTF有2种:UTF-8和UTF-16
其中UTF-16和上面提到的Unicode本身的编码规范是一致的,这里不多说了。而UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容,这样做的好处是压缩了字符在西欧一些国家的内存消耗,减少了不必要的资源浪费,这在实际应用中是非常有必要的。
UTF-8有点类似于Haffman编码,它将Unicode编码为:
7F的字符,用单个字节来表示;
80-7FF的字符用两个字节表示 (中文的编码范围)
800-FFFF的字符用3字节表示
因为目前为止Unicode-16规范没有指定FFFF以上的字符,所以UTF-8最多是使用3个字节来表示一个字符。但理论上来说,UTF-8最多需要用6字节表示一个字符。
在UTF-8里,英文字符仍然跟ASCII编码一样,因此原先的函数库可以继续使用。而中文的编码范围是在0080-07FF之间,因此是2个字节表示(但这两个字节和GB编码的两个字节是不同的)。
 

base64编码

  按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
适用范围
Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java持久化系统Hibenate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。
为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。
另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+”,“*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。
此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)

 

 

 

 

 

 
posted on 2016-08-21 00:42  别拿曾经看以后  阅读(2007)  评论(0编辑  收藏  举报