这篇文章上次修改于 1609 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
ASCII
ASCII 字符对照表
二进制 | 十进制 | 十六进制 | 字符/缩写 | 解释 | |
---|---|---|---|---|---|
00000000 | 0 | 00 | NUL (NULL) | 空字符 | |
00000001 | 1 | 01 | SOH (Start Of Headling) | 标题开始 | |
00000010 | 2 | 02 | STX (Start Of Text) | 正文开始 | |
00000011 | 3 | 03 | ETX (End Of Text) | 正文结束 | |
00000100 | 4 | 04 | EOT (End Of Transmission) | 传输结束 | |
00000101 | 5 | 05 | ENQ (Enquiry) | 请求 | |
00000110 | 6 | 06 | ACK (Acknowledge) | 回应/响应/收到通知 | |
00000111 | 7 | 07 | BEL (Bell) | 响铃 | |
00001000 | 8 | 08 | BS (Backspace) | 退格 | |
00001001 | 9 | 09 | HT (Horizontal Tab) | 水平制表符 | |
00001010 | 10 | 0A | LF/NL(Line Feed/New Line) | 换行键 | |
00001011 | 11 | 0B | VT (Vertical Tab) | 垂直制表符 | |
00001100 | 12 | 0C | FF/NP (Form Feed/New Page) | 换页键 | |
00001101 | 13 | 0D | CR (Carriage Return) | 回车键 | |
00001110 | 14 | 0E | SO (Shift Out) | 不用切换 | |
00001111 | 15 | 0F | SI (Shift In) | 启用切换 | |
00010000 | 16 | 10 | DLE (Data Link Escape) | 数据链路转义 | |
00010001 | 17 | 11 | DC1/XON (Device Control 1/Transmission On) | 设备控制1/传输开始 | |
00010010 | 18 | 12 | DC2 (Device Control 2) | 设备控制2 | |
00010011 | 19 | 13 | DC3/XOFF (Device Control 3/Transmission Off) | 设备控制3/传输中断 | |
00010100 | 20 | 14 | DC4 (Device Control 4) | 设备控制4 | |
00010101 | 21 | 15 | NAK (Negative Acknowledge) | 无响应/非正常响应/拒绝接收 | |
00010110 | 22 | 16 | SYN (Synchronous Idle) | 同步空闲 | |
00010111 | 23 | 17 | ETB (End of Transmission Block) | 传输块结束/块传输终止 | |
00011000 | 24 | 18 | CAN (Cancel) | 取消 | |
00011001 | 25 | 19 | EM (End of Medium) | 已到介质末端/介质存储已满/介质中断 | |
00011010 | 26 | 1A | SUB (Substitute) | 替补/替换 | |
00011011 | 27 | 1B | ESC (Escape) | 逃离/取消 | |
00011100 | 28 | 1C | FS (File Separator) | 文件分割符 | |
00011101 | 29 | 1D | GS (Group Separator) | 组分隔符/分组符 | |
00011110 | 30 | 1E | RS (Record Separator) | 记录分离符 | |
00011111 | 31 | 1F | US (Unit Separator) | 单元分隔符 | |
00100000 | 32 | 20 | (Space) | 空格 | |
00100001 | 33 | 21 | ! | ||
00100010 | 34 | 22 | " | ||
00100011 | 35 | 23 | # | ||
00100100 | 36 | 24 | $ | ||
00100101 | 37 | 25 | % | ||
00100110 | 38 | 26 | & | ||
00100111 | 39 | 27 | ' | ||
00101000 | 40 | 28 | ( | ||
00101001 | 41 | 29 | ) | ||
00101010 | 42 | 2A | * | ||
00101011 | 43 | 2B | + | ||
00101100 | 44 | 2C | , | ||
00101101 | 45 | 2D | - | ||
00101110 | 46 | 2E | . | ||
00101111 | 47 | 2F | / | ||
00110000 | 48 | 30 | 0 | ||
00110001 | 49 | 31 | 1 | ||
00110010 | 50 | 32 | 2 | ||
00110011 | 51 | 33 | 3 | ||
00110100 | 52 | 34 | 4 | ||
00110101 | 53 | 35 | 5 | ||
00110110 | 54 | 36 | 6 | ||
00110111 | 55 | 37 | 7 | ||
00111000 | 56 | 38 | 8 | ||
00111001 | 57 | 39 | 9 | ||
00111010 | 58 | 3A | : | ||
00111011 | 59 | 3B | ; | ||
00111100 | 60 | 3C | < | ||
00111101 | 61 | 3D | = | ||
00111110 | 62 | 3E | > | ||
00111111 | 63 | 3F | ? | ||
01000000 | 64 | 40 | @ | ||
01000001 | 65 | 41 | A | ||
01000010 | 66 | 42 | B | ||
01000011 | 67 | 43 | C | ||
01000100 | 68 | 44 | D | ||
01000101 | 69 | 45 | E | ||
01000110 | 70 | 46 | F | ||
01000111 | 71 | 47 | G | ||
01001000 | 72 | 48 | H | ||
01001001 | 73 | 49 | I | ||
01001010 | 74 | 4A | J | ||
01001011 | 75 | 4B | K | ||
01001100 | 76 | 4C | L | ||
01001101 | 77 | 4D | M | ||
01001110 | 78 | 4E | N | ||
01001111 | 79 | 4F | O | ||
01010000 | 80 | 50 | P | ||
01010001 | 81 | 51 | Q | ||
01010010 | 82 | 52 | R | ||
01010011 | 83 | 53 | S | ||
01010100 | 84 | 54 | T | ||
01010101 | 85 | 55 | U | ||
01010110 | 86 | 56 | V | ||
01010111 | 87 | 57 | W | ||
01011000 | 88 | 58 | X | ||
01011001 | 89 | 59 | Y | ||
01011010 | 90 | 5A | Z | ||
01011011 | 91 | 5B | [ | ||
01011100 | 92 | 5C | \ | ||
01011101 | 93 | 5D | ] | ||
01011110 | 94 | 5E | ^ | ||
01011111 | 95 | 5F | _ | ||
01100000 | 96 | 60 | ` | ||
01100001 | 97 | 61 | a | ||
01100010 | 98 | 62 | b | ||
01100011 | 99 | 63 | c | ||
01100100 | 100 | 64 | d | ||
01100101 | 101 | 65 | e | ||
01100110 | 102 | 66 | f | ||
01100111 | 103 | 67 | g | ||
01101000 | 104 | 68 | h | ||
01101001 | 105 | 69 | i | ||
01101010 | 106 | 6A | j | ||
01101011 | 107 | 6B | k | ||
01101100 | 108 | 6C | l | ||
01101101 | 109 | 6D | m | ||
01101110 | 110 | 6E | n | ||
01101111 | 111 | 6F | o | ||
01110000 | 112 | 70 | p | ||
01110001 | 113 | 71 | q | ||
01110010 | 114 | 72 | r | ||
01110011 | 115 | 73 | s | ||
01110100 | 116 | 74 | t | ||
01110101 | 117 | 75 | u | ||
01110110 | 118 | 76 | v | ||
01110111 | 119 | 77 | w | ||
01111000 | 120 | 78 | x | ||
01111001 | 121 | 79 | y | ||
01111010 | 122 | 7A | z | ||
01111011 | 123 | 7B | { | ||
01111100 | 124 | 7C | \ | ||
01111101 | 125 | 7D | } | ||
01111110 | 126 | 7E | ~ | ||
01111111 | 127 | 7F | DEL (Delete) | 删除 |
UTF8 编码
UTF-8使用一至六个字节为每个字符编码(尽管如此,2003年11月UTF-8被RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF,也就是说最多四个字节):
- 128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F)。
- 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码(Unicode范围由U+0080至U+07FF)。
- 其他基本多文种平面(BMP)中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(Unicode范围由U+0800至U+FFFF)。
- 其他极少使用的Unicode 辅助平面的字符使用四至六字节编码(Unicode范围由U+10000至U+1FFFFF使用四字节,Unicode范围由U+200000至U+3FFFFFF使用五字节,Unicode范围由U+4000000至U+7FFFFFFF使用六字节)。
对上述提及的第四种字符而言,UTF-8使用四至六个字节来编码似乎太耗费资源了。但UTF-8对所有常用的字符都可以用三个字节表示,而且它的另一种选择,UTF-16编码,对前述的第四种字符同样需要四个字节来编码,所以要决定UTF-8或UTF-16哪种编码比较有效率,还要视所使用的字符的分布范围而定。不过,如果使用一些传统的压缩系统,比如DEFLATE,则这些不同编码系统间的的差异就变得微不足道了。若顾及传统压缩算法在压缩较短文字上的效果不大,可以考虑使用Unicode标准压缩格式(SCSU)。
Unicode字符的比特被分割为数个部分,并分配到UTF-8的字节串中较低的比特的位置。在U+0080的以下字符都使用内含其字符的单字节编码。这些编码正好对应7比特的ASCII字符。在其他情况,有可能需要多达4个字符组来表示一个字符。这些多字节的最高有效比特会设置成1,以防止与7比特的ASCII字符混淆,并保持标准的字节主导字符串运作顺利。
代码范围 十六进制 | 标量值(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 |
例如,希伯来语字母aleph(א)的Unicode代码是U+05D0,按照以下方法改成UTF-8:
- 它属于U+0080到U+07FF区域,这个表说明它使用双字节,110yyyyy 10zzzzzz.
- 十六进制的0x05D0换算成二进制就是101-1101-0000.
- 这11位数按顺序放入"y"部分和"z"部分:11010111 10010000.
- 最后结果就是双字节,用十六进制写起来就是0xD7 0x90,这就是这个字符aleph(א)的UTF-8编码。
所以开始的128个字符(US-ASCII)只需一字节,接下来的1920个字符需要双字节编码,包括带附加符号的拉丁字母,希腊字母,西里尔字母,科普特语字母,亚美尼亚语字母,希伯来文字母和阿拉伯字母的字符。基本多文种平面中其余的字符使用三个字节,剩余字符使用四个字节。
根据这种方式可以处理更大数量的字符。原来的规范允许长达6字节的序列,可以覆盖到31位(通用字符集原来的极限)。尽管如此,2003年11月UTF-8被RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF。根据这些规范,以下字节值将无法出现在合法UTF-8序列中:
编码(二进制) | 编码(十六进制) | 注释 |
---|---|---|
1100000x | C0, C1 | 过长编码:双字节序列的头字节,但码点 <= 127 |
1111111x | FE, FF | 无法达到:7或8字节序列的头字节 |
111110xx 1111110x | F8, F9, FA, FB, FC, FD | 被RFC 3629规范:5或6字节序列的头字节 |
11110101 1111011x | F5, F6, F7 | 被RFC 3629规范:码点超过10FFFF的头字节 |
UTF-8编码字节含义
- 对于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),可判断编码是否有错误或数据传输过程中是否有错误
UTF8 特性
- UCS字符U+0000到U+007F(ASCII)被编码为字节0x00到0x7F(ASCII兼容),这也意味着只包含7位ASCII字符的文件在ASCII和UTF-8两种编码方式下是一样的。
- 所有>U+007F的UCS字符被编码为一个多个字节的串,每个字节都有标记位集。因此,ASCII字节(0x00-0x7F)不可能作为任何其他字符的一部分。
- 表示非ASCII字符的多字节串的第一个字节总是在0xC0到0xFD的范围里,并指出这个字符包含多少个字节。多字节串的其余字节都在0x80到0xBF范围里,这使得重新同步非常容易,并使编码无国界,且很少受丢失字节的影响。
- 可以编入所有可能的231个UCS代码
- UTF-8编码字符理论上可以最多到6个字节长,然而16位BMP字符最多只用到3字节长。
- Bigendian UCS-4字节串的排列顺序是预定的。
- 字节0xFE和0xFF在UTF-8编码中从未用到,同时,UTF-8以字节为编码单元,它的字节顺序在所有系统中都是一様的,没有字节序的问题,也因此它实际上并不需要BOM。
- 与UTF-16或其他Unicode编码相比,对于不支持Unicode和XML的系统,UTF-8更不容易造成问题。
UTF-8 | |
---|---|
最小码位 | 0000 |
最大码位 | 10FFFF |
每字节所占位数 | 8 bits |
Byte order | N/A |
每个字符最小字节数 | 1 |
每个字符最大字节数 | 4 |
Unicode
Unicode,中文又称万国码、国际码、统一码、单一码,是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。
Unicode伴随着通用字符集的标准而发展,同时也以书本的形式[1]对外发表。Unicode至今仍在不断增修,每个新版本都加入更多新的字符。目前最新的版本为2020年3月公布的13.0.0[2],已经收录超过13万个字符)(第十万个字符在2005年获采纳)。Unicode涵盖的资料除了视觉上的字形、编码方法、标准的字符编码外,还包含了字符特性,如大小写字母。
Unicode的发展由非营利机构统一码联盟负责,该机构致力于让Unicode方案取代既有的字符编码方案。因为既有的方案往往空间非常有限,亦不适用于多语环境。
Unicode备受认可,并广泛地应用于电脑软件的国际化与本地化过程。有很多新科技,如可扩展置标语言(Extensible Markup Language,简称:XML)、Java编程语言以及现代的操作系统,都采用Unicode编码。
实现方式
Unicode的实现方式不同于编码方式。一个字符的Unicode编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicod转换格式(Unicode Transformation Format,简称为UTF)。
例如,如果一个仅包含基本7位ASCII字符的Unicode 文件,如果每个字符都使用2字节的原 Unicode编码传输,其第一字节的8位始终为0。这就造成了比较大的浪费。对于这种情况,可以使用UTF-8编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补 0)。而遇到与其他 Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1 进行识别。这样对以7位ASCII字符为主的西文文档就大幅节省了编码长度(具体方案参见UTF-8)。类似的,对未来会出现的需要 4个字节的辅助平面字符和其他 UCS-4 扩充字符,2字节编码的UTF-16也需要通过一定的算法进行转换。
Python 中的 str、bytes、Unicode
- str是字符数据(如:文本,给人看的),bytes和bytearray是字节数据(如:二进制数据,给计算机看的),它们都是序列,可以进行迭代遍历。
- str和bytes是不可变序列,通过str类型的通用函数,比如find()、replace()、islower()等函数修改后实际上是重新创建了新对象;bytearray是可变序列,可以原处修改字节。
- bytes和bytearray都能使用str类型的通用函数,比如find()、replace()、islower()等,不能用的是str的格式化操作。
- python 3.x中默认str是unicode格式编码的,例如UTF-8字符集。
Python 中解析 bytes 中的中文字符和特殊符号及特殊含义字符
前面找了很多背景知识作为铺垫,相信大家对编码和字符集也都有了了解。
当我们在解析 dex 文件中字符时会遇到特殊符合或特殊含义的字符,若我们不加任何判断的去解析时会报各种各样的错误。遇到的错误如下:
python3 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 0: invalid start byte
类似这样的错误会遇到很多,这里是 c0 不能解析,还有几个 utf8 不能解析的特殊字符。
我用了一个偷懒的方法,并没有自己按照UTF8 转换中文规则去解析,而是使用了 codecs 这个库处理了,忽略了对报错特殊含义的字节解析,将其置为‘空字符+’ 占位.
def read_strings(data, header_data):
strings = []
string_ids_off = header_data['string_ids_off']
for i in range(header_data['string_ids_size']):
offset = struct.unpack('<L', data[string_ids_off + (i * 4):string_ids_off + (i * 4) + 4])[0]
c_size = data[offset]
c_char = data[offset + 1:offset + 1 + c_size]
c_char = codecs.decode(c_char, encoding='utf-8', errors='ignore')
print(f'c_char = {c_char}')
strings.append(c_char)
return strings
没有评论