ISO/IEC 10646-1定义了一个大的字符集, 叫做Universal Character Set(UCS). 包纳了世
界上多数的书写系统. 但是, 最开始通过的UCS的编码, 和许多现在的程序和协议不兼容,
这就导致了UTF-8的开发, 也就是这个memo所描述的. utf8保留了完整的US-ASCII范围, 提
供了和文件系统, parser以及其他依靠US-ASCII, but are transparent to other
values..
10646..... Unicode标准也定义了相同的字符集合, 还进一步定义了额外的字符属性以及实
现者感兴趣的其他程序细节. 到目前为止, Unicode的改变和10646的增订都是相互跟进的,
因此两者的character repertoires和code point的分配仍旧是同步的.
ISO/IEC 10646和Unicode给他们的常用repertoire定义了一些编码形式: UTF-8, UCS-2,
UTF-16, UCS-4以及UTF-32. 在一个编码格式(encoding form)中, 每一个字符都是一个或者
多个编码单元的形式呈现的. 除了UTF-8之外的所有标准UCS编码格式的编码单元都大于一个
字节, 这使得他们在目前许多的使用8甚至是7个bit字符的程序和协议中难以使用.
而这里讲到的UTF-8, 则是使用单字节的编码单元. 使用一个字节(octec, 8bit字节)中的所
有bit, 但是保留了完整的US-ASCII范围: US-ASCII字符编码为一个有着寻常US-ASCII值的
字节,所有值在这个范围的字节都只用来标示一个US-ASCII字符.
UTF-8以变长字节数的形式编码UCS字符, 其中字节的数目, 每个字节的值, 都取决于在
ISO/IEC 10646中分配给字符的整数值(character number, 也就是(...), code
position,code point或者Unicode scalar value). 这个编码形式有一些特点(所有的数值
都是十六进制)
UTF-8由Ken Thompson在1992年9月根据Rob Pike指定的设计标准, 以定义一个可以以非破坏
性的方式用于Plan9操作系统的UCS转换格式为目标, 制定的. 汤普森的设计xxxx, 最后成为
了UTF-8
UTF-8由Unicode标准定义. xxx
在UTF-8中, U+0000到U+10FFFF范围的字符(UTF-16可及范围)使用1到四个字节的序列编码.
单字节序列唯一的一个字节的最高位bit为0, 剩下的7个bit用于编码字符编号. 在一个n个
字节的序列中(n > 1), 初始字节的高n个bit设置wei 0, 之后是一个设置为0的bit. 该字节
中剩下的bit包含来自要被编码的字符中的bit. 之后的字节的高位bit设置为1, 之后的bit
设置为0, 剩下6个bit用于编码要被编码的字符的bit.
下面这个表总结了不同的字节类型. 字符x标示对应的bit可以用于编码字符编号.
Char. number range | UTF-8 octet sequence
(hexadecimal) | (binary)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
将一个字符编码为UTF-8的过程如下:
UTF的定义禁止编码U+D800到U+DFFF之间的字符编号, 这些是保留给UTF-16编码格式的(as
surrogate pairs(??)), 不直接标示字符. 当以UTF-8格式编码UTF-16数据的时候, 需要先
解码UTF-16数据来获得字符编号, 之后再按照上面的方法编码为UTF-8. 这个和CESU-8不同(
一个类似UTF-8的编码, 不是针对互联网使用的). CESU-8操作类似UTF-8但是编码UTF-16值
而非字符编码(code point). 这会导致对在0xFFFF智商的字符编号出现不同的结果, 这些字
符的CESU-8编码在UTF-8中是不合法的.
(被这个搞糊了, UTF16不干我事啊,真是要命)
解码UTF-8字符的按照如下过程进行:
对以上解码算法的实现必须要防止对非法序列的解码. 比如, 某些天真的实现可能会将过长
的UTF-8序列C0 80解码为字符U+0000(本来只要使用一个字节编码的), 或者将surrogate
pair, ED A1 8C ED BE B4, 解码为U+233B4(???). 解码非法序列可能会有安全影响或者导
致其他问题.
(11101101,10100001,10001100,11101101,10111110,10110100)
(1101100001001100 ==> D84C) (1101111110110100 ==> DFB4)
(???)
这里给出一个ABNF语法
UTF8-octets = *( UTF8-char )
UTF8-char = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
UTF8-1 = %x00-7F
UTF8-2 = %xC2-DF UTF8-tail
UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
%xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
%xF4 %x80-8F 2( UTF8-tail )
UTF8-tail = %x80-BF
(UTF-3编码的要大于07FF, ED 80那里可能是,D800-DFFF的范围吧...不包含D800-DFFF)
UCS 字符U+FEFF "ZERO WIDTH NO-BREAK SPACE", 也被非正式地成为"BYTE ORDER MARK".(
还真有这个字符, 看起来光标卡了一下一样, 得多按一下..), 可以用作文本中的0长度空格
. 但是其BOM的名称表明了这个字符的第二个可能额用法. 给一个UCS字符流前缀一个U+FEFF
字符作为"签名"... 收到这样一个流序列的接受者可以使用初始字符看作是流由UCS字符构
成的提示,以及识别涉及到了那个UCS编码, 以及, 对于有多字节编码单元(UTF-8不是的吧
..), 作为识别字节顺序的一种方式.. UTF-8是用的是单字节的编码单元, 最有一个功能是
没用的,BOM总是序列EF BB BF的形式.
很重要的一点是, 要知道, 除了出现在流开始位置, 任何U+FEFF都必须非解释为0宽度
non-breaking space, 不能解释为签名. 解释为签名的时候, Unicode标准建议将初始的
U+FEFF字符在处理文本之后移除. 在一些情况下, 这个移除是必须的.(比如, 在剪接两个字
符串的时候, 不这样做的话, 可能会导致出现不必要的0宽空格), 但是xxxx. 因此推荐忽略
而非去除, 只在真的必要的时候, 移除...
(不管就好了..)
原文:https://www.cnblogs.com/jakio6/p/11740952.html