Swift String
该图片由OpenClipart-Vectors在Pixabay上发布
编码
ASCII
ASCII
((American Standard Code for Information Interchang
): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。
ASCII
码使用指定的7位
或8位
二进制数组合来表示128
或256
种可能的字符。标准ASCII码也叫基础ASCII码,使用7位二进制数
(剩下的1位二进制为0)来表示所有的大写
和小写字母
,数字0到9
、标点符号
,以及在美式英语中使用的特殊控制字符
。
- 表示
0~31
及127
(共33个)是控制字符或通信专用字符(其余为可显示字符)- 如控制符:
LF
(换行)、CR
(回车)、FF
(换页)、DEL
(删除)、BS
(退格)、BEL
(响铃)等; - 通信专用字符:
SOH
(文头)、EOT
(文尾)、ACK
(确认)等;ASCII
值为8、9、10 和13 分别转换为退格、制表、换行和回车字符。 - 它们并没有特定的图形显示,但会依不同的应用程序,而对文本显示有不同的影响。
- 如控制符:
32~126
(共95个)是字符(32是空格),其中48~57
为0到9十个阿拉伯数字。65~90
为26个大写英文字母97~122
号为26个小写英文字母- 其余为一些标点符号、运算符号等(详见文末附录)。
- 常见ASCII码的大小规则:
0~9<A~Z<a~z
。- 数字比字母要小。如 “7”<“F”;
- 数字0比数字9要小,并按0到9顺序递增。如 “3”<“8” ;
- 字母A比字母Z要小,并按A到Z顺序递增。如“A”<“Z” ;
- 同个字母的大写字母比小写字母要小32。如“A”<“a” 。
- 几个常见字母的ASCII码大小:
“A”为65
;“a”为97
;“0”为 48
ISO/IEC 8859
对于非英语的文字,或者受众不是美国人的时候,ASCII 编码就不够了。其他国家和语言需要不一样的字符 (就连同样说英语的英国人都需要一个表示英镑的
£
符号),其中绝大多数需要的字符用七个比特是放不下的。ISO/IEC 8859
使用了额外的第八个比特,并且在 ASCII 范围外又定义了 16 种不同的编码。比如第 1 部分(ISO/IEC 8859-1,又叫 Latin-1),涵盖多种西欧语言;以及第 5 部分,涵盖那些使用西里尔 (俄语) 字母的语言。
ISO-8859-1
编码是单字节编码,向下兼容ASCII
,其编码范围是0x00-0xFF
0x00-0x7F
之间完全和ASCII
一致0x80-0x9F
之间是控制字符0xA0-0xFF
之间是文字符号。
此字符集支持部分于欧洲使用的语言,包括阿尔巴尼亚语、巴斯克语、布列塔尼语、加泰罗尼亚语、丹麦语、荷兰语、法罗语、弗里西语、加利西亚语、德语、格陵兰语、冰岛语、爱尔兰盖尔语、意大利语、拉丁语、卢森堡语、挪威语、葡萄牙语、里托罗曼斯语、苏格兰盖尔语、西班牙语及瑞典语。
Unicode
-
起因
如果你想按照 ISO/IEC 8859 来用土耳其语书写关于古希腊的内容,那你就不怎么走运了。因为你只能在第 7 部分 (Latin/Greek) 或者第 9 部分 (Turkish) 中选一种。另外,八个比特对于许多语言的编码来说依然是不够的。比如第 6 部分 (Latin/Arabic) 没有包括书写乌尔都语或者波斯语这样的阿拉伯字母语言所需要的字符。同时,在从 ASCII 的下半区替换了少量字符后,我们才能用八比特去编码基于拉丁字母但同时又有大量变音符组合的越南语。而其他东亚语言则完全不能被放入八个比特中。
-
选择
当固定宽度的编码空间被用完后,有两种选择:
- 选择增加宽度
- 切换到可变长的编码。
最初的时候,
Unicode
被定义成两个字节固定宽度的格式,这种格式现在被称为UCS-2
。不过这已经是现实问题出现之前的决定了,而且大家也都承认其实两个字节也还是不够用,四个字节的话在大多数情况下又太低效。 -
组成
所以今天的 Unicode 是一个可变长格式。它的可变长特性有两种不同的意义:
- 由编码单元 (
code unit
) 组成 Unicode 标量 (Unicode scalar
); - 由
Unicode
标量组成字符。
- 由编码单元 (
-
表示
在表示一个
Unicode
的字符时,通常会用U+
然后紧接着一组十六进制的数字来表示这一个字符。 -
层次
Unicode
编码系统,可分为- 编码方式
- 实现方式
-
编码方式
统一码的编码方式与
ISO 10646
的通用字符集概念相对应。当前实际应用的统一码版本对应于UCS-2
,使用 16 位的编码空间。也就是每个字符占用2 个字节
。这样理论上一共最多可以表示 216(即 65536)个字符。基本满足各种语言的使用。实际上当前版本的统一码并未完全使用这 16 位编码,而是保留了大量空间以作为特殊使用或将来扩展。 -
实现方式
Unicode
的实现方式不同于编码方式。一个字符的Unicode
编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode
编码的实现方式有所不同。Unicode
的实现方式称为Unicode
转换格式(Unicode Transformation Format
,简称为UTF
)。
UTF-8
UTF-8(8-bit Unicode Transformation Format
)是一种针对Unicode
的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode
标准中的任何字符,且其编码中的第一个字节仍与ASCII
兼容,这使得原来处理ASCII
字符的软件无须或只须做少部分修改,即可继续使用。
UTF-8以字节为单位对Unicode
进行编码。
编码字节含义:
- 对于UTF-8编码中的任意字节B,如果B的第一位为0,则B独立的表示一个字符(ASCII码);
- 如果B的第一位为1,第二位为0,则B为一个多字节字符中的一个字节(非ASCII字符);
- 如果B的前两位为1,第三位为0,则B为两个字节表示的字符中的第一个字节;
- 如果B的前三位为1,第四位为0,则B为三个字节表示的字符中的第一个字节;
- 如果B的前四位为1,第五位为0,则B为四个字节表示的字符中的第一个字节;
因此,对UTF-8编码中的任意字节,根据第一位,可判断是否为ASCII字符;根据前二位,可判断该字节是否为一个字符编码的第一个字节;根据前四位(如果前两位均为1),可确定该字节为字符编码的第一个字节,并且可判断对应的字符由几个字节表示;根据前五位(如果前四位为1),可判断编码是否有错误或数据传输过程中是否有错误。
Unicode
和 UTF-8
之间的转换关系表 ( x
字符表示码点占据的位 )
码点的位数 | 码点起值 | 码点终值 | 字节序列 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 |
---|---|---|---|---|---|---|---|---|---|
7 | U+0000 | U+007F | 1 | 0xxxxxxx | |||||
11 | U+0080 | U+07FF | 2 | 110xxxxx | 10xxxxxx | ||||
16 | U+0800 | U+FFFF | 3 | 1110xxxx | 10xxxxxx | 10xxxxxx | |||
21 | U+10000 | U+1FFFFF | 4 | 11110xxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | ||
26 | U+200000 | U+3FFFFFF | 5 | 111110xx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | |
31 | U+4000000 | U+7FFFFFFF | 6 | 1111110x | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx | 10xxxxxx |
转换示例:
下面由 D
,o
,g
,‼
(DOUBLE EXCLAMATION MARK
, Unicode 标量 U+203C
)和 🐶(DOG FACE,Unicode
标量为 U+1F436
)组成的字符串中的每一个字符代表着一种不同的表示:
let dogString = "Dog‼🐶"
可以通过遍历 String
的 utf8
属性来访问它的 UTF-8
表示。其为 String.UTF8View
类型的属性,UTF8View
是无符号 8 位(UInt8
)值的集合,每一个 UInt8
值都是一个字符的 UTF-8
表示:
let dogString = "Dog‼🐶"
dogString.utf8.forEach { print($0) }
// 68 111 103 226 128 188 240 159 144 182
Character | D U+0044 |
o U+006F |
g U+0067 |
‼ U+203C |
🐶 U+1F436 |
|||||
---|---|---|---|---|---|---|---|---|---|---|
UTF-8 Code Unit | 68 | 111 | 103 | 226 | 128 | 188 | 240 | 159 | 144 | 182 |
hexadecimal | 0x44 | 0x6F | 0x67 | 0xE2 | 0x80 | 0xBC | 0xF0 | 0X9F | 0x90 | 0XB6 |
Position | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
前三个 10 进制 codeUnit
值(68
、111
、103
)代表了字符 D
、o
和 g
,它们的 UTF-8
表示与 ASCII
表示相同。接下来的三个 10 进制 codeUnit
值(226
、128
、188
)是 DOUBLE EXCLAMATION MARK
的3字节 UTF-8
表示。最后的四个 codeUnit
值(240
、159
、144
、182
)是 DOG FACE
的4字节 UTF-8
表示。
以下以 🐶 为例做转换:
-
由转换关系表可知
U+1F436
转换后的格式为, 其中码点需要 21 位(x
的个数)1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
-
1F436
的二进制数表示为, 一共 20 位,不足码点的占位数(21位),因此需要在前面补0,凑齐码点的占位数(21位)0001 1111 0100 0011 0110
-
补齐后的二进制数为
0 0001 1111 0100 0011 0110
-
把补齐后的二进制数依次替换掉占位码点(
x
)1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx 000 01 1111 01 0000 11 0110 || || || \/ 1111 0000 1001 1111 1001 0000 1011 0110
-
转换为 16 进制
二进制 1111 0000 1001 1111 1001 0000 1011 0110 十六进制 0xF0 0x9F 0x90 0xB6 十进制 240 159 144 182
UTF-16
UTF-16以16位无符号整数为单位对Unicode进行编码.
Unicode的编码空间从U+0000
到U+10FFFF
,共有1,112,064
个码位(code point
)可用来映射字符.
Unicode的编码空间可以划分为16个平面(plane
),每个平面包含216 (65,536)个码位。16个平面的码位可表示为从U+xx0000
到U+xxFFFF
,其中xx
表示十六进制值从0016 到 1016 ,共计16个平面。第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP
),或称第零平面(Plane 0
)。其他平面称为辅助平面(Supplementary Planes
)。
基本多语言平面内,从U+D800
到U+DFFF
之间的码位区块是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF
区块的码位来对辅助平面的字符的码位进行编码。
UTF-16 编码规则如下(其中 U
= Unicode; WORD
= 16位无符号整数):
- 如果
U<0x10000
,U的UTF-16编码就是U
对应的WORD
。 - 如果
U≥0x10000
,我们先计算U'=U-0x10000
,然后将U'
写成二进制形式:yyyy yyyy yyxx xxxx xxxx
,U
的UTF-16编码(二进制)就是:1101 10yy yyyy yyyy 1101 11xx xxxx xxxx
。
针对上述UTF-8的编码示例,以下使用 UTF-16进行编码:
可以通过遍历 String 的 utf16 属性来访问Dog‼🐶
的 UTF-16 表示。其为 String.UTF16View 类型的属性,UTF16View 是无符号16位(UInt16)值的集合,每一个 UInt16 都是一个字符的 UTF-16 表示:
let dogString = "Dog‼🐶"
dogString.utf16.forEach { print($0) }
// 68 111 103 8252 55357 56374
Character | D U+0044 |
o U+006F |
g U+0067 |
‼ U+203C |
🐶 U+1F436 |
|
---|---|---|---|---|---|---|
UTF-16 Code Unit | 68 | 111 | 103 | 8252 | 55357 | 56374 |
hexadecimal | 0x44 | 0x6F | 0x67 | 0x203C | 0xD83D | 0xDC36 |
Position | 0 | 1 | 2 | 3 | 4 | 5 |
前三个 codeUnit
值(68、111、103
)代表了字符 D
、o
和 g
,它们的 UTF-16
代码单元和 UTF-8
完全相同(因为这些 Unicode
标量表示 ASCII
字符)。
第四个 codeUnit
值(8252
)是一个等于十六进制 203C
的的十进制值。这个代表了 DOUBLE EXCLAMATION MARK
字符的 Unicode
标量值 U+203C
。这个字符在 UTF-16 中可以用一个代码单元表示。
第五和第六个 codeUnit
值(55357
和 56374
)是 DOG FACE
字符的 UTF-16
表示。第一个值为 U+D83D
(十进制值为 55357
),第二个值为 U+DC36
(十进制值为 56374
)。
编码过程如下:
-
0x1F436
转换为二进制数据为:0001 1111 0100 0011 0110
-
0x1F436
>0x10000
; 所以U' = 0x1F436 - 0x10000 = 0xF436 二进制数据如下: U' = 0000 1111 0100 0011 0110
-
将
U'
填入模板中1101 10yy yyyy yyyy 1101 11xx xxxx xxxx 00 0011 1101 00 0011 0110 || || || \/ 1101 1000 0011 1101 1101 1100 0011 0110
-
转换为 16 进制
二进制 1101 1000 0011 1101 1101 1100 0011 0110 十六进制 0xD83D 0xDC36 十进制 55357 56374
UTF-16 问答
-
为什么
U'
可以被写成20个二进制位?Unicode
的最大码位是0x10FFFF
,减去0x10000
后,U'
的最大值是0xFFFFF
,所以肯定可以用20个二进制位表示。 -
什么是代理区(
Surrogate
)?当
Unicode
编码为0x10000-0x10FFFF
之间时,该Unicode
的UTF-16
编码有两个WORD,- 第一个WORD的高6位是
110110
, - 第二个WORD的高6位是
110111
。
第一个WORD的取值范围(二进制)是
1101 1000 0000 0000
到1101 1011 1111 1111
,即0xD800-0xDBFF
。 第二个WORD的取值范围(二进制)是1101 1100 0000 0000
到1101 1111 1111 1111
,即0xDC00-0xDFFF
。为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编码的设计者将
0xD800-0xDFFF
保留下来,并称为代理区(Surrogate
):Unicode编码 描述 D800-DB7F High Surrogates(高位替代) DB80-DBFF High Private Use Surrogates(高位专用替代) DC00-DFFF Low Surrogates(低位替代) 高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。 低位替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。
- 第一个WORD的高6位是
-
什么是高位专用替代?
如果一个字符的UTF-16编码的第一个WORD在
0xDB80
到0xDBFF
之间,那么它的Unicode编码在什么范围内? 我们知道第二个WORD的取值范围是0xDC00-0xDFFF
,所以这个字符的UTF-16编码范围应该是0xDB80 0xDC00
到0xDBFF 0xDFFF
。我们将这个范围写成二进制:1101 1011 1000 0000 1101 1100 0000 0000 ~ 1101 1011 1111 1111 1101 1111 1111 1111
按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到
1110 0000 0000 0000 0000 ~ 1111 1111 1111 1111 1111
即
0xE0000-0xFFFFF
, 按照编码的相反步骤再加上0x10000
,得到0xF0000-0x10FFFF
。 这就是UTF-16编码的第一个WORD在0xDB80
到0xDBFF
之间的Unicode编码范围,即平面15和平面16。 因为Unicode标准将平面15和平面16都作为专用区,所以0xDB80
到0xDBFF
之间的保留码位被称作高位专用替代。
Unicode 标量
除了代理区(0xDB80-0xDFFF
)外所有码点, 都是Unicode标量。
标量在 Swift 字符串字面量中以 \u{xxxx}
来表示,其中的 xxxx
是十六进制的数字。
比如欧元符号 €
在 Swift 中写作 \u{20AC}
。
Unicode 标量在 Swift 中对应的类型是 Unicode.Scalar
,它是一个对 UInt32
的封装类型。
扩展字位簇
从用户视角看到的一个字符,称为扩展字位簇(extended grapheme cluster
)。
用户所认为的在屏幕上显示的“单个字符”可能仍需要多个编码点组合而成。
在 Swift 中,字位簇由 Character
类型进行表示,这个类型可以对任意数量的标量进行编码,并形成一个从用户角度来看的字符。
如下图所示, 字符(Character
)é
, 由两个Unicode标量 \u{65}
和 \u{301}
组合而成,但从用户视角而言仍是一个字符。
// 查看Unicode标量
let double = "Poke\u{301}mon"
double.unicodeScalars.forEach { print($0) }
// 结果如下:
P
o
k
e
́
m
o
n
// 查看UTF-16
let double = "Poke\u{301}mon"
double.unicodeScalars.forEach { print($0) }
// 结果如下:
80
111
107
101
769
109
111
110
标准等价
上述字符 é
除了用Unicode标量 \u{65}
和 \u{301}
组合表示,还可以用一个Unicode标量 \u{00E9}
表示。
这两种写法的显示结果相同,Unicode规范将此称作标准等价(canonically equivalent)。
Swift能够正确处理这种情况
let single = "Pok\u{00E9}mon"
let double = "Poke\u{301}mon"
-
显示结果一致
(single, double) // (Pokémon, Pokémon)
-
字符数相等
single.count // 7 double.count // 7
-
比较结果也相等
single == double // true
-
深入到编码单元层面就能看到差异
// UTF-8 single.utf8.count // 8 double.utf8.count // 9 // UTF-16 single.utf16.count // 7 double.utf16.count // 8
String 和 NSString 的差异
NSString
的 Unicode 表示方式为 \Uxxxxxxxx
。
NSString *singleStr = @"Pok\U000000E9mon";
NSString *doubleStr = @"Poke\U00000301mon";
singleStr.length; // 7
doubleStr.length; // 8
[singleStr isEqualToString:doubleStr]; // NO
对 NSString
而言, 会在 UTF-16
编码单元的层面上按字面值做一次比较,而不会将不同字符组合起来的等价性纳入考虑。其他语言的大部分字符串 API 也都是这么做的。
如果需要进行标准的比较,需要使用 compare:
方法:
[singleStr compare:doubleStr] == NSOrderedSame; // YES
String
获取Unicode名字
将 Unicode 标量转换为它们对应的官方 Unicode 名字
extension StringTransform {
static let toUnicodeName = StringTransform("Any-Name")
}
extension Unicode.Scalar {
var unicodeName: String {
let name = String(self).applyingTransform(.toUnicodeName, reverse: false)!
let prefixPattern = "\\N{"
let suffixPattern = "}"
let prefixLength = name.hasPrefix(prefixPattern) ? prefixPattern.count : 0
let suffixLength = name.hasSuffix(suffixPattern) ? suffixPattern.count : 0
return String(name.dropFirst(prefixLength).dropLast(suffixLength))
}
}
let dogString = "Dog‼🐶"
dogString.unicodeScalars.forEach { print($0.unicodeName) }
// LATIN CAPITAL LETTER D
// LATIN SMALL LETTER O
// LATIN SMALL LETTER G
// DOUBLE EXCLAMATION MARK
// DOG FACE
字符串和集合
String
是Character
值的集合。
在 Swift 2
和 Swift 3
中 String
本身并非 Collection
。
因为在处理字符串某些边界情况下不满足集合的一般算法;
例:
let flagLetterC = "🇨"
let flagLetterN = "🇳"
let flag = flagLetterC + flagLetterN // 🇨🇳
flag.count // 1
flag.count == flagLetterC.count + flagLetterN.count // false
所以由字符组成的集合被移动到了 characters
属性里,它和 unicodeScalars
,utf8
以及 utf16
等其他集合视图类似,是一种字符串的表现形式。
但是这个改动增加了学习难度且降低了易用性。
所以在 Swift 4
里,String
又成为了 Collection
。characters
视图依然存在,但是仅仅是为了代码的前向兼容。
BidirectionalCollection
String 虽然是集合,但是不支持随机访问。
就算知道给定字符串中第 n
个字符的位置,也并不会对计算这个字符之前有多少个 Unicode
标量有任何帮助。
所以,String
只实现了 BidirectionalCollection
。你可以从字符串的头或者尾开始,向后或者向前移动,代码会察看毗邻字符的组合,跳过正确的字节数。不管怎样,你每次只能迭代一个字符。
当你在书写一些字符串处理的代码时,需要将这个性能影响时刻牢记在心。
例:生成一个包含所有前缀子字符串的数组
时间复杂度为 O(n2)版本
extension String {
var allPrefixes1: [Substring] {
return (0...self.count).map(self.prefix)
}
}
let hello = "Hello"
hello.allPrefixes1 // ["", "H", "He", "Hel", "Hell", "Hello"]
时间复杂度为 O(n)版本
extension String {
var allPrefixes2: [Substring] {
return [""] + self.indices.map { index in self[...index] }
}
}
hello.allPrefixes2 // ["", "H", "He", "Hel", "Hell", "Hello"]
字符串索引
Swift 不允许使用整数值对字符串进行下标操作。
因为整数的下标访问无法在常数时间内完成,而且查找第 n
个 Character
的操作也必须要对它之前的所有字节进行检查。
String.Index
是String
和它的视图所使用的索引类型,它本质上是一个存储了从字符串开头的字节偏移量的不透明值。如果你想计算第n
个字符所对应的索引,你依然从字符串的开头或结尾开始,并花费O(n)
的时间。但是一旦你拥有了有效的索引,就可以通过索引下标以O(1)
的时间对字符串进行访问了。至关重要的是,通过一个已有索引来寻找下一个索引也是很快的,因为你可以从这个已有索引的字节偏移量开始进行查找,而不需要从头开始。正是由于这个原因,按顺序 (前向或者后向) 对字符串中的字符进行迭代是一个高效操作。
子字符串
和所有集合类型一样,
String
有一个特定的SubSequence
类型,它就是Substring
。Substring
和ArraySlice
很相似:它是一个以不同起始和结束索引的对原字符串的切片。子字符串和原字符串共享文本存储,这带来的巨大的好处,它让对字符串切片成为了非常高效的操作。
StringProtocol
Substring
和String
的接口几乎完全一样。这是通过一个叫做StringProtocol
的通用协议来达到的,String
和Substring
都遵守这个协议。 因为几乎所有的字符串API
都被定义在StringProtocol
上,对于Substring
,你完全可以假装将它看作就是一个String
,并完成各项操作。 不过,在某些时候,你还是需要将子字符串转回String
实例;和所有的切片一样,子字符串也只能用于短期的存储,这可以避免在操作过程中发生昂贵的复制。 当这个操作结束,你想将结果保存起来,或是传递给下一个子系统,这时你应该通过初始化方法从Substring
创建一个新的String
String(subString)
附录
ASCII码表
Bin
(二进制)
| Oct
(八进制)
| Dec
(十进制)
| Hex
(十六进制)
| 缩写/字符
| 解释
|
0000 0000
| 00
| 0
| 0x00
| NUL(null)
| 空字符
|
0000 0001
| 01
| 1
| 0x01
| SOH(start of headline)
| 标题开始
|
0000 0010
| 02
| 2
| 0x02
| STX (start of text)
| 正文开始
|
0000 0011
| 03
| 3
| 0x03
| ETX (end of text)
| 正文结束
|
0000 0100
| 04
| 4
| 0x04
| EOT (end of transmission)
| 传输结束
|
0000 0101
| 05
| 5
| 0x05
| ENQ (enquiry)
| 请求
|
0000 0110
| 06
| 6
| 0x06
| ACK (acknowledge)
| 收到通知
|
0000 0111
| 07
| 7
| 0x07
| BEL (bell)
| 响铃
|
0000 1000
| 010
| 8
| 0x08
| BS (backspace)
| 退格
|
0000 1001
| 011
| 9
| 0x09
| HT (horizontal tab)
| 水平制表符
|
0000 1010
| 012
| 10
| 0x0A
| LF (NL line feed, new line)
| 换行键
|
0000 1011
| 013
| 11
| 0x0B
| VT (vertical tab)
| 垂直制表符
|
0000 1100
| 014
| 12
| 0x0C
| FF (NP form feed, new page)
| 换页键
|
0000 1101
| 015
| 13
| 0x0D
| CR (carriage return)
| 回车键
|
0000 1110
| 016
| 14
| 0x0E
| SO (shift out)
| 不用切换
|
0000 1111
| 017
| 15
| 0x0F
| SI (shift in)
| 启用切换
|
0001 0000
| 020
| 16
| 0x10
| DLE (data link escape)
| 数据链路转义
|
0001 0001
| 021
| 17
| 0x11
| DC1 (device control 1)
| 设备控制1
|
0001 0010
| 022
| 18
| 0x12
| DC2 (device control 2)
| 设备控制2
|
0001 0011
| 023
| 19
| 0x13
| DC3 (device control 3)
| 设备控制3
|
0001 0100
| 024
| 20
| 0x14
| DC4 (device control 4)
| 设备控制4
|
0001 0101
| 025
| 21
| 0x15
| NAK (negative acknowledge)
| 拒绝接收
|
0001 0110
| 026
| 22
| 0x16
| SYN (synchronous idle)
| 同步空闲
|
0001 0111
| 027
| 23
| 0x17
| ETB (end of trans. block)
| 结束传输块
|
0001 1000
| 030
| 24
| 0x18
| CAN (cancel)
| 取消
|
0001 1001
| 031
| 25
| 0x19
| EM (end of medium)
| 媒介结束
|
0001 1010
| 032
| 26
| 0x1A
| SUB (substitute)
| 代替
|
0001 1011
| 033
| 27
| 0x1B
| ESC (escape)
| 换码(溢出)
|
0001 1100
| 034
| 28
| 0x1C
| FS (file separator)
| 文件分隔符
|
0001 1101
| 035
| 29
| 0x1D
| GS (group separator)
| 分组符
|
0001 1110
| 036
| 30
| 0x1E
| RS (record separator)
| 记录分隔符
|
0001 1111
| 037
| 31
| 0x1F
| US (unit separator)
| 单元分隔符
|
0010 0000
| 040
| 32
| 0x20
| (space)
| 空格
|
0010 0001
| 041
| 33
| 0x21
| !
| 叹号 |
0010 0010
| 042
| 34
| 0x22
| "
| 双引号 |
0010 0011
| 043
| 35
| 0x23
| #
| 井号 |
0010 0100
| 044
| 36
| 0x24
| $
| 美元符 |
0010 0101
| 045
| 37
| 0x25
| %
| 百分号 |
0010 0110
| 046
| 38
| 0x26
| &
| 和号 |
0010 0111
| 047
| 39
| 0x27
| '
| 闭单引号 |
0010 1000
| 050
| 40
| 0x28
| (
| 开括号
|
0010 1001
| 051
| 41
| 0x29
| )
| 闭括号
|
0010 1010
| 052
| 42
| 0x2A
| *
| 星号 |
0010 1011
| 053
| 43
| 0x2B
| +
| 加号 |
0010 1100
| 054
| 44
| 0x2C
| ,
| 逗号 |
0010 1101
| 055
| 45
| 0x2D
| -
| 减号/破折号 |
0010 1110
| 056
| 46
| 0x2E
| .
| 句号 |
0010 1111
| 057
| 47
| 0x2F
| /
| 斜杠 |
0011 0000
| 060
| 48
| 0x30
| 0
| 字符0 |
0011 0001
| 061
| 49
| 0x31
| 1
| 字符1 |
0011 0010
| 062
| 50
| 0x32
| 2
| 字符2 |
0011 0011
| 063
| 51
| 0x33
| 3
| 字符3 |
0011 0100
| 064
| 52
| 0x34
| 4
| 字符4 |
0011 0101
| 065
| 53
| 0x35
| 5
| 字符5 |
0011 0110
| 066
| 54
| 0x36
| 6
| 字符6 |
0011 0111
| 067
| 55
| 0x37
| 7
| 字符7 |
0011 1000
| 070
| 56
| 0x38
| 8
| 字符8 |
0011 1001
| 071
| 57
| 0x39
| 9
| 字符9 |
0011 1010
| 072
| 58
| 0x3A
| :
| 冒号 |
0011 1011
| 073
| 59
| 0x3B
| ;
| 分号 |
0011 1100
| 074
| 60
| 0x3C
| <
| 小于 |
0011 1101
| 075
| 61
| 0x3D
| =
| 等号 |
0011 1110
| 076
| 62
| 0x3E
| >
| 大于 |
0011 1111
| 077
| 63
| 0x3F
| ?
| 问号 |
0100 0000
| 0100
| 64
| 0x40
| @
| 电子邮件符号 |
0100 0001
| 0101
| 65
| 0x41
| A
| 大写字母A |
0100 0010
| 0102
| 66
| 0x42
| B
| 大写字母B |
0100 0011
| 0103
| 67
| 0x43
| C
| 大写字母C |
0100 0100
| 0104
| 68
| 0x44
| D
| 大写字母D |
0100 0101
| 0105
| 69
| 0x45
| E
| 大写字母E |
0100 0110
| 0106
| 70
| 0x46
| F
| 大写字母F |
0100 0111
| 0107
| 71
| 0x47
| G
| 大写字母G |
0100 1000
| 0110
| 72
| 0x48
| H
| 大写字母H |
0100 1001
| 0111
| 73
| 0x49
| I
| 大写字母I |
01001010
| 0112
| 74
| 0x4A
| J
| 大写字母J |
0100 1011
| 0113
| 75
| 0x4B
| K
| 大写字母K |
0100 1100
| 0114
| 76
| 0x4C
| L
| 大写字母L |
0100 1101
| 0115
| 77
| 0x4D
| M
| 大写字母M |
0100 1110
| 0116
| 78
| 0x4E
| N
| 大写字母N |
0100 1111
| 0117
| 79
| 0x4F
| O
| 大写字母O |
0101 0000
| 0120
| 80
| 0x50
| P
| 大写字母P |
0101 0001
| 0121
| 81
| 0x51
| Q
| 大写字母Q |
0101 0010
| 0122
| 82
| 0x52
| R
| 大写字母R |
0101 0011
| 0123
| 83
| 0x53
| S
| 大写字母S |
0101 0100
| 0124
| 84
| 0x54
| T
| 大写字母T |
0101 0101
| 0125
| 85
| 0x55
| U
| 大写字母U |
0101 0110
| 0126
| 86
| 0x56
| V
| 大写字母V |
0101 0111
| 0127
| 87
| 0x57
| W
| 大写字母W |
0101 1000
| 0130
| 88
| 0x58
| X
| 大写字母X |
0101 1001
| 0131
| 89
| 0x59
| Y
| 大写字母Y |
0101 1010
| 0132
| 90
| 0x5A
| Z
| 大写字母Z |
0101 1011
| 0133
| 91
| 0x5B
| [
| 开方括号 |
0101 1100
| 0134
| 92
| 0x5C
| \
| 反斜杠 |
0101 1101
| 0135
| 93
| 0x5D
| ]
| 闭方括号 |
0101 1110
| 0136
| 94
| 0x5E
| ^
| 脱字符 |
0101 1111
| 0137
| 95
| 0x5F
| _
| 下划线 |
0110 0000
| 0140
| 96
| 0x60
| `
| 开单引号 |
0110 0001
| 0141
| 97
| 0x61
| a
| 小写字母a |
0110 0010
| 0142
| 98
| 0x62
| b
| 小写字母b |
0110 0011
| 0143
| 99
| 0x63
| c
| 小写字母c |
0110 0100
| 0144
| 100
| 0x64
| d
| 小写字母d |
0110 0101
| 0145
| 101
| 0x65
| e
| 小写字母e |
0110 0110
| 0146
| 102
| 0x66
| f
| 小写字母f |
0110 0111
| 0147
| 103
| 0x67
| g
| 小写字母g |
0110 1000
| 0150
| 104
| 0x68
| h
| 小写字母h |
0110 1001
| 0151
| 105
| 0x69
| i
| 小写字母i |
0110 1010
| 0152
| 106
| 0x6A
| j
| 小写字母j |
0110 1011
| 0153
| 107
| 0x6B
| k
| 小写字母k |
0110 1100
| 0154
| 108
| 0x6C
| l
| 小写字母l |
0110 1101
| 0155
| 109
| 0x6D
| m
| 小写字母m |
0110 1110
| 0156
| 110
| 0x6E
| n
| 小写字母n |
0110 1111
| 0157
| 111
| 0x6F
| o
| 小写字母o |
0111 0000
| 0160
| 112
| 0x70
| p
| 小写字母p |
0111 0001
| 0161
| 113
| 0x71
| q
| 小写字母q |
0111 0010
| 0162
| 114
| 0x72
| r
| 小写字母r |
0111 0011
| 0163
| 115
| 0x73
| s
| 小写字母s |
0111 0100
| 0164
| 116
| 0x74
| t
| 小写字母t |
0111 0101
| 0165
| 117
| 0x75
| u
| 小写字母u |
0111 0110
| 0166
| 118
| 0x76
| v
| 小写字母v |
0111 0111
| 0167
| 119
| 0x77
| w
| 小写字母w |
0111 1000
| 0170
| 120
| 0x78
| x
| 小写字母x |
0111 1001
| 0171
| 121
| 0x79
| y
| 小写字母y |
0111 1010
| 0172
| 122
| 0x7A
| z
| 小写字母z |
0111 1011
| 0173
| 123
| 0x7B
| {
| 开花括号 |
0111 1100
| 0174
| 124
| 0x7C
| |
| 垂线 |
0111 1101
| 0175
| 125
| 0x7D
| }
| 闭花括号 |
0111 1110
| 0176
| 126
| 0x7E
| ~
| 波浪号 |
0111 1111
| 0177
| 127
| 0x7F
| DEL (delete)
| 删除
|