不论是web开发或是移动开发,在不同场景总是需要用的编码的转换,之前一直没有去深入的研究其中的转换关系,今天抽空学习了下(字符编码介绍很多,我只是将之间的关系总结了下,具体介绍可自行wiki)。
先介绍下几种主要的编码方式ASCII、Unicode、UTF-8、GBK、BASE64、URLEncode。
- ASCII:美国信息交换标准代码,是基于拉丁字母的一套电脑编码系统,只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,现在的软件系统大多采用Unicode。7位字符集,支持128个字符。
- Unicode:固定长度2字节,16位字符集,最多支持2^16个字符。因为ASCII码只有7位,Unicode表示ASCII码,会用0补齐,会造成浪费所以又再次基础上扩展出了UTF-8等变长编码方案。
- UTF-8:是一种针对Unicode的可变长度字符编码,也是一种前缀码。通过1-6个字节表示不同编码,非固定长度,通过编码前缀来区分不同编码。
代码范围
十六进制标量值(scalar value)
二进制UTF-8
二进制/十六进制注释 000000 - 00007F
128个代码00000000 00000000 0zzzzzzz 0zzzzzzz(00-7F) ASCII字符范围,字节由零开始 七个z 七个z 000080 - 0007FF
1920个代码00000000 00000yyy yyzzzzzz 110yyyyy(C0-DF) 10zzzzzz(80-BF) 第一个字节由110开始,接着的字节由10开始 三个y;二个y;六个z 五个y;六个z 000800 - 00D7FF
00E000 - 00FFFF
61440个代码 [Note 1]00000000 xxxxyyyy yyzzzzzz 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz 第一个字节由1110开始,接着的字节由10开始 四个x;四个y;二个y;六个z 四个x;六个y;六个z 010000 - 10FFFF
1048576个代码000wwwxx xxxxyyyy yyzzzzzz 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz 将由11110开始,接着的字节由10开始 三个w;二个x;四个x;四个y;二个y;六个z 三个w;六个x;六个y;六个z - GBK:汉字内码扩展规范,这个就不多介绍了:
GBK的编码范围 范围 第1字节 第2字节 编码数 字数 水准 GBK/1 A1
–A9
A1
–FE
846 717 水准 GBK/2 B0
–F7
A1
–FE
6,768 6,763 水准 GBK/3 81
–A0
40
–FE
(7F
除外)6,080 6,080 水准 GBK/4 AA
–FE
40
–A0
(7F
除外)8,160 8,160 水准 GBK/5 A8
–A9
40
–A0
(7F
除外)192 166 用户定义 AA
–AF
A1
–FE
564 用户定义 F8
–FE
A1
–FE
658 用户定义 A1
–A7
40
–A0
(7F
除外)672 合计: 23,940 21,886 - BASE64:ASCII、Unicode、UTF-8编码其实建立的是字符与字符编码的对应关系(即字符->字符编码),BASE64、URLEncode是建立在这些字符集上用于在一些特殊场景中的编码转换方案(字符编码->字符)。BASE64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个位元为一个单元,对应某个可打印字符。三个字节有24个位元,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。3byte的原始字符编码数据需要使用4个打印字符表示,64个打印字符包括大小写26个英文字母10个数字“+”、“/"、"=",因此经过base64编码后的数据长度约为原长度的4/3。
Base64索引表:
Value Char Value Char Value Char Value Char 0 A 16 Q 32 g 48 w 1 B 17 R 33 h 49 x 2 C 18 S 34 i 50 y 3 D 19 T 35 j 51 z 4 E 20 U 36 k 52 0 5 F 21 V 37 l 53 1 6 G 22 W 38 m 54 2 7 H 23 X 39 n 55 3 8 I 24 Y 40 o 56 4 9 J 25 Z 41 p 57 5 10 K 26 a 42 q 58 6 11 L 27 b 43 r 59 7 12 M 28 c 44 s 60 8 13 N 29 d 45 t 61 9 14 O 30 e 46 u 62 + 15 P 31 f 47 v 63 / - URLEncode:URL编码,是特定上下文的统一资源定位符 (URI)的编码机制,URI所允许的字符分作保留与未保留,保留字符具有特殊含义( 例如:斜线字符用于URL (或者更一般的, URI)不同部分的分界),未保留字符没有这些特殊含义,URI中的其它字符必须用百分号编码。
如果一个保留字符在特定上下文中具有特殊含义(称作"reserved purpose") , 且URI中必须使用该字符用于其它目的, 那么该字符必须百分号编码. 百分号编码一个保留字符,首先需要把该字符的ASCII的值表示为两个16进制的数字,然后在其前面放置转义字符("%
"),置入URI中的相应位置。(对于非ASCII字符, 需要转换为UTF-8字节序, 然后每个字节按照上述方式表示.)
RFC 3986 section 2.2 保留字符 (2005年1月) !
*
'
(
)
;
:
@
&
=
+
$
,
/
?
#
[
]
RFC 3986 section 2.3 未保留字符 (2005年1月) A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
0
1
2
3
4
5
6
7
8
9
-
_
.
~
给个简单的例子,看看编码间的转换:
“我”对应的uncode码(java和net中string存储字符使用的就是unicode,string toCharArray之后的字符的值即为unicode码值):0110 0010 0001 0001 ,u6211
utf-8表示2个字节使用的标量值1110xxxx(E0-EF) 10yyyyyy 10zzzzzz(6z+6y+4x=2*8),unicode的2进制码转换utf-8:1110 0110 100010 00 1001 0001,16进制码为0xE6 0x88 0x91
对上面的UTF-8编码结果进行Base64编码过程,拆分1110 0110 100010 00 1001 0001为111001、101000、100010、01000对应十进制数值57、40、34、17,码表中的字符5oiR,即对应的BASE64字符串。