|
|
本帖最后由 不点 于 2021-3-24 18:36 编辑
由于不知道要发在哪里,所以就发在这里了;有鉴于 Linux 对 UTF8 的支持比较完善,而 Windows 的 cmd 命令行对 UTF8 的支持目前还没有,将来有没有,还不好说。【更正:Win10 的控制台支持 UTF8;XP 和 Win7 的控制台不支持 UTF8】
又由于是“摸着石头过河”,不知道要写多少个帖子,所以,先占位前 30 个楼层。
标题的含义,大家可以这么理解:《关于 UTF8 的思考》或《UTF8 的改进、完善、补充》
发帖的形式是“无定形”,想到哪,写到哪。就好比是“随笔”、“日记”、“博客”。
今天准备搜集一些基础资料,温习基本概念,作为铺垫。
好的,先搜到这个: https://www.crockford.com/utf8.html
全文照搬过来:
2019-06-24
UTF-8
UTF-8 is one of the smartest things I've seen. It is a byte stream encoding for simple values (like Unicode characters) that can be bigger than bytes. UTF-8 has some wonderful properties:
- ASCII is a proper subset, so all ASCII encoded streams are also UTF-8 streams.
- The first byte of a multi-byte character tells the number of bytes.
- Continuation bytes are easily distinguished from first bytes.
- The sort order is preserved, not that matters for Unicode.
A first byte can contain between 2 and 7 bits of data. A first byte also determines the number of continuation bytes. Each continuation byte carries 6 bits of data.
UTF-8 has one unfortunate disadvantage, that many 16-bit characters are encoded in 3 bytes. This disadvantage is more than offset by its advantages, and by having a single, simple encoding that can work in all languages and contexts. The benefits range from greater reliability to better security. That is why JSON recommends UTF-8. UTF-8 is the good stuff. Thank you, Ken Thompson.
In my own work, I use a formulation that works well with 32-bit characters.
| Binary | Hex | Thru | Range | Thru | Continuation
Bytes | Total
Data Bits | | 0xxxxxxx | 00 | 7F | 00 | 7F | 0 | 7 | | 10xxxxxx | 80 | BF | continuation | 6 | | 110xxxxx | C0 | DF | 80 | 7FF | 1 | 11 | | 1110xxxx | E0 | EF | 800 | FFFF | 2 | 16 | | 11110xxx | F0 | F7 | 1 0000 | 1F FFFF | 3 | 21 | | 111110xx | F8 | FB | 20 0000 | 3FF FFFF | 4 | 26 | | 111111xx | FC | FF | 400 0000 | FFFF FFFF | 5 | 32 |
印象中,UTF8 只处理最低的 31 位,最高的那一位是留待以后扩展的,目前不处理。所以,上述表格的最后一行是不太准确的。准确的似乎应该是这样:
| 1111110x | FC | FD | 400 0000 | 7FFF FFFF | 5 | 31 |
不过,这个细节无关紧要,因为现实中很少需要用那么大的代码点。
字节序 —— Byte Order Mark
字节序是一个特殊的 Unicode 字符,它的码点是 U+FEFF,不是 U+FFFE。它的 UTF8 表示是 EF BB BF。有时候,我们需要死记硬背。怎么样才能记住它?需要有一些联想或技巧。我们试着把 U+FFFE 转为 UTF8 字节串:它的十六进制表示是 EF BF BE,它的二进制表示是 11101111 10111111 10111110。它是个偶数,因此末尾是 0。它比 U+FFFF 只小 1,所以,除了末尾是 0,其他位都是 1,全都撑满了(除非按照 UTF8 规范某位只能为 0)。总结一下有下面这些特征,可以帮助记忆:
1、BOM(U+FEFF)是个奇数,不是偶数。其末尾是 F 不是 E。
2、BOM(U+FEFF)距离 16 位最大值 U+FFFF 较远,因此,它不是 U+FFFE。
3、U+FFFE 是noncharacter(非字符),也就是没有对它进行定义,或者说,它不是个正常的字符。因此,BOM 不是它。
4、位于 U+FFF0 至 U+FFFF 之间的 16 个字符,属于“特殊字符”范围,而 BOM (U+FEFF)位于此范围之外,而且距离较远。
5、BOM(U+FEFF)中的两个字节是 8 位整数中最大的两个字节 FF 和 FE,不会是 EF,因此,不要误记为 U+FFEF 或 U+EFFF 之类的。
6、BOM(U+FEFF)只能是 U+FEFF 和 U+FFFE 两者之一,而 U+FFFE 距离最大值U+FFFF 太近,予以排除。
7、BOM(U+FEFF)距离 U+FF00 较近: FEFF = FF00 - 1。
8、BOM(U+FEFF)恰好位于末尾的 256 个字符之外,也就是说,紧贴着末尾的 256 个字符。(此处末尾是指 BMP 的末尾)。
零宽不断行空格——Zero Width No-Break Space
历史上,BOM 曾经是唯一一个“零宽不断行空格”,现在新增了一个零宽不断行字符 U+2060(其正式名称叫做 word joiner,单词贴合器),而 BOM 就主要用作“字节序标记符”了。
非字符—— Non-Characters
在 17 个平面(Planes)中,每个平面结尾的 2 个码点,都是 non-character。这样就有了 34 个非字符。而在基本多语言平面(BMP)中,又定义了 32 个 non-characters:U+FDD0 ~ U+FDEF
所以,总共有 66 个非字符。这 66 个非字符是程序员可以私自使用的字符,不能用于公共交换的目的。
拉丁 1 补充字符 —— Latin-1 Supplement
在 ASCII 之外的所有字符中,码点 U+0080 ~ U+00FF 显然最重要,它们在码值上位于传统单字节字符的范围(有时称为“扩展的 ASCII 字符”),但不幸的是在 UTF8 的表示中需要占用两个字节。
unicode | utf8 | hex | binary | binary | hex | 80
| 10000000
| 11000010 10000000
| C2 80
| 81
| 10000001
| 11000010 10000001
| C2 81
| 82
| 10000010
| 11000010 10000010
| C2 82
| 83
| 10000011
| 11000010 10000011
| C2 83
| 84
| 10000100
| 11000010 10000100
| C2 84
| 85
| 10000101
| 11000010 10000101
| C2 85
| 86
| 10000110
| 11000010 10000110
| C2 86
| 87
| 10000111
| 11000010 10000111
| C2 87
| 88
| 10001000
| 11000010 10001000
| C2 88
| 89
| 10001001
| 11000010 10001001
| C2 89
| | 8A | 10001010
| 11000010 10001010
| C2 8A
| | 8B | 10001011
| 11000010 10001011
| C2 8B
| | 8C | 10001100
| 11000010 10001100
| C2 8C
| | 8D | 10001101
| 11000010 10001101
| C2 8D
| | 8E | 10001110
| 11000010 10001110
| C2 8E
| | 8F | 10001111
| 11000010 10001111
| C2 8F
| 90
| 10010000
| 11000010 10010000
| C2 90
| 91
| 10010001
| 11000010 10010001
| C2 91
| 92
| 10010010
| 11000010 10010010
| C2 92
| 93
| 10010011
| 11000010 10010011
| C2 93
| 94
| 10010100
| 11000010 10010100
| C2 94
| 95
| 10010101
| 11000010 10010101
| C2 95
| 96
| 10010110
| 11000010 10010110
| C2 96
| 97
| 10010111
| 11000010 10010111
| C2 97
| 98
| 10011000
| 11000010 10011000
| C2 98
| 99
| 10011001
| 11000010 10011001
| C2 99
| | 9A | 10011010
| 11000010 10011010
| C2 9A
| | 9B | 10011011
| 11000010 10011011
| C2 9B
| | 9C | 10011100
| 11000010 10011100
| C2 9C
| | 9D | 10011101
| 11000010 10011101
| C2 9D
| | 9E | 10011110
| 11000010 10011110
| C2 9E
| | 9F | 10011111
| 11000010 10011111
| C2 9F
| | A0 | 10100000
| 11000010 10100000
| C2 A0
| | A1 | 10100001
| 11000010 10100001
| C2 A1
| | A2 | 10100010
| 11000010 10100010
| C2 A2
| | A3 | 10100011
| 11000010 10100011
| C2 A3
| | A4 | 10100100
| 11000010 10100100
| C2 A4
| | A5 | 10100101
| 11000010 10100101
| C2 A5
| | A6 | 10100110
| 11000010 10100110
| C2 A6
| | A7 | 10100111
| 11000010 10100111
| C2 A7
| | A8 | 10101000
| 11000010 10101000
| C2 A8
| | A9 | 10101001
| 11000010 10101001
| C2 A9
| | AA | 10101010
| 11000010 10101010
| C2 AA
| | AB | 10101011
| 11000010 10101011
| C2 AB
| | AC | 10101100
| 11000010 10101100
| C2 AC
| | AD | 10101101
| 11000010 10101101
| C2 AD
| | AE | 10101110
| 11000010 10101110
| C2 AE
| | AF | 10101111
| 11000010 10101111
| C2 AF
| | B0 | 10110000
| 11000010 10110000
| C2 B0
| | B1 | 10110001
| 11000010 10110001
| C2 B1
| | B2 | 10110010
| 11000010 10110010
| C2 B2
| | B3 | 10110011
| 11000010 10110011
| C2 B3
| | B4 | 10110100
| 11000010 10110100
| C2 B4
| | B5 | 10110101
| 11000010 10110101
| C2 B5
| | B6 | 10110110
| 11000010 10110110
| C2 B6
| | B7 | 10110111
| 11000010 10110111
| C2 B7
| | B8 | 10111000
| 11000010 10111000
| C2 B8
| | B9 | 10111001
| 11000010 10111001
| C2 B9
| | BA | 10111010
| 11000010 10111010
| C2 BA
| | BB | 10111011
| 11000010 10111011
| C2 BB
| | BC | 10111100
| 11000010 10111100
| C2 BC
| | BD | 10111101
| 11000010 10111101
| C2 BD
| | BE | 10111110
| 11000010 10111110
| C2 BE
| | BF | 10111111
| 11000010 10111111
| C2 BF
| | C0 | 11000000
| 11000011 10000000
| C3 80
| | C1 | 11000001
| 11000011 10000001
| C3 81
| | C2 | 11000010
| 11000011 10000010
| C3 82
| | C3 | 11000011
| 11000011 10000011
| C3 83
| | C4 | 11000100
| 11000011 10000100
| C3 84
| | C5 | 11000101
| 11000011 10000101
| C3 85
| | C6 | 11000110
| 11000011 10000110
| C3 86
| | C7 | 11000111
| 11000011 10000111
| C3 87
| | C8 | 11001000
| 11000011 10001000
| C3 88
| | C9 | 11001001
| 11000011 10001001
| C3 89
| | CA | 11001010
| 11000011 10001010
| C3 8A
| | CB | 11001011
| 11000011 10001011
| C3 8B
| | CC | 11001100
| 11000011 10001100
| C3 8C
| | CD | 11001101
| 11000011 10001101
| C3 8D
| | CE | 11001110
| 11000011 10001110
| C3 8E
| | CF | 11001111
| 11000011 10001111
| C3 8F
| | D0 | 11010000
| 11000011 10010000
| C3 90
| | D1 | 11010001
| 11000011 10010001
| C3 91
| | D2 | 11010010
| 11000011 10010010
| C3 92
| | D3 | 11010011
| 11000011 10010011
| C3 93
| | D4 | 11010100
| 11000011 10010100
| C3 94
| | D5 | 11010101
| 11000011 10010101
| C3 95
| | D6 | 11010110
| 11000011 10010110
| C3 96
| | D7 | 11010111
| 11000011 10010111
| C3 97
| | D8 | 11011000
| 11000011 10011000
| C3 98
| | D9 | 11011001
| 11000011 10011001
| C3 99
| | DA | 11011010
| 11000011 10011010
| C3 9A
| | DB | 11011011
| 11000011 10011011
| C3 9B
| | DC | 11011100
| 11000011 10011100
| C3 9C
| | DD | 11011101
| 11000011 10011101
| C3 9D
| | DE | 11011110
| 11000011 10011110
| C3 9E
| | DF | 11011111
| 11000011 10011111
| C3 9F
| | E0 | 11100000
| 11000011 10100000
| C3 A0
| | E1 | 11100001
| 11000011 10100001
| C3 A1
| | E2 | 11100010
| 11000011 10100010
| C3 A2
| | E3 | 11100011
| 11000011 10100011
| C3 A3
| | E4 | 11100100
| 11000011 10100100
| C3 A4
| | E5 | 11100101
| 11000011 10100101
| C3 A5
| | E6 | 11100110
| 11000011 10100110
| C3 A6
| | E7 | 11100111
| 11000011 10100111
| C3 A7
| | E8 | 11101000
| 11000011 10101000
| C3 A8
| | E9 | 11101001
| 11000011 10101001
| C3 A9
| | EA | 11101010
| 11000011 10101010
| C3 AA
| | EB | 11101011
| 11000011 10101011
| C3 AB
| | EC | 11101100
| 11000011 10101100
| C3 AC
| | ED | 11101101
| 11000011 10101101
| C3 AD
| | EE | 11101110
| 11000011 10101110
| C3 AE
| | EF | 11101111
| 11000011 10101111
| C3 AF
| | F0 | 11110000
| 11000011 10110000
| C3 B0
| | F1 | 11110001
| 11000011 10110001
| C3 B1
| | F2 | 11110010
| 11000011 10110010
| C3 B2
| | F3 | 11110011
| 11000011 10110011
| C3 B3
| | F4 | 11110100
| 11000011 10110100
| C3 B4
| | F5 | 11110101
| 11000011 10110101
| C3 B5
| | F6 | 11110110
| 11000011 10110110
| C3 B6
| | F7 | 11110111
| 11000011 10110111
| C3 B7
| | F8 | 11111000
| 11000011 10111000
| C3 B8
| | F9 | 11111001
| 11000011 10111001
| C3 B9
| | FA | 11111010
| 11000011 10111010
| C3 BA
| | FB | 11111011
| 11000011 10111011
| C3 BB
| | FC | 11111100
| 11000011 10111100
| C3 BC
| | FD | 11111101
| 11000011 10111101
| C3 BD
| | FE | 11111110
| 11000011 10111110
| C3 BE
| | FF | 11111111
| 11000011 10111111
| C3 BF
|
位于 U+0000~U+00FF 这个范围的字符,有时还称为 binary 字符。这大概是因为,在传统上文件被粗略地分为“文本文件” 和 “非文本文件”。文本文件很可能粗略地认为是只含 ASCII 字符的文件(实际上文本文件很可能也不应该包含 00 以及其他一些控制字符),而非文本文件,也就粗略地认为是含有任意字符的文件(传统上的字符,就是字节;当 8 位字符不够用的时候,才有了 16 位字符和 32 位字符;字节始终是 8 位),也就是二进制文件。JavaScript 有 binary string 的概念,意思是“由 U+0000~U+00FF 这个范围中的字符所组成的字符串”。
unicode 扩展了字符的范围,然而,传统上“字节”这个概念,在 unicode 里面却无法体现。传统上,文件是以字节为单位来表示的,一个文件,可以由单一字节构成。unicode 是 4 字节的,没法处理这种情况。UTF8 虽然能处理单字节,但是位于 0x80 ~ 0xFF 的单字节,却是非法的 UTF8 字节串,没法处理。JavaScript 必须引入 ArrayBuffer 之类的东西,才能处理传统的字节空间。科技进步了,怎么问题反而多了,处理方法也复杂了? 有没有一个办法,让 UTF8 能够直接处理任意的字节空间?
|
|