Top Banner
UTFBOM的常见问题 zsjforcn 2011-08-30 1
47

Utf和bom的常见问题

Jul 21, 2015

Download

Documents

Sanji Zhang
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Utf和bom的常见问题

UTF和BOM的常见问题

zsjforcn

2011-08-30

1

Page 2: Utf和bom的常见问题

• http://unicode.org/faq/utf_bom.html

英原文

• http://hi.baidu.com/zsjforcn/blog/

作者博客

• 以下slides中90%以上都是枯燥乏味的文字,爱看美女帅哥片

子的人站到一边!O(∩_∩)O哈哈~

• 本slides并不完全忠于英原文,存在删节!

说在前面

2

Page 3: Utf和bom的常见问题

涉及UTF或

编码形式的

一般性问题

UTF-8的常

见问题

UTF-16的常

见问题

UTF-32的常

见问题

BOM的常

见问题

3

Page 4: Utf和bom的常见问题

涉及UTF或编码形式的一般性问题

Q:Unicode是16位编码的吗?

Q:Unicode文本可以有多种表示吗?

Q:什么是UTF?

Q:有哪些字节序不是由UTF生成的?如何表示它们?

Q:应该支持哪些UTF编码形式?

Q:各种UTF编码之间的区别是什么?

Q:有没有标准的方法来包装一个Unicode字符使其符合8位ASCII流?

4

Page 5: Utf和bom的常见问题

Q:Unicode是16位编码的吗?

• A:不是。1991年到1995年第一版Unicode确实是16位编码,但自从Unicode2.0(1996年7月)它再也不是16位编码了。Unicode标

准编码字符集从U+0000到U+10FFFF,总共

有21位编码空间。根据你自己的需要选择

不同的编码形式:UTF-8,UTF-16或者UTF-32,每个字符会被表示成1到4个8位字节,

1到2个16位字或者1个32位双字。

5

Page 6: Utf和bom的常见问题

Q:Unicode文本可以有多种表示吗?

• A:可以。有多种表示Unicode数据的方式,包括UTF-8,UTF-16和UTF-32。另外,还有

一些压缩转换的方式,例如,Unicode技术

标准#6:Unicode的一种标准压缩方案

(SCSU)。

6

Page 7: Utf和bom的常见问题

Q:什么是UTF?

• A:Unicode转换格式(UTF)是一种算法,它将每个Unicode编码点(除了代理编码点)映射到一个唯一的字节序上。

• 每种UTF都是可逆的。故,每种UTF都支持“无损压缩行程”:将任何Unicode编码的字符S映射到一串字节序上,而反过来也会生成S。为了保证此行程,UTF映射“必须”也将所有不合法的Unicode字符编码点映射到唯一的字节序上。这些非法的编码点包含了66个非字符(从FFFE到FFFF)和其他代理。

• 虽然SCSU压缩方式是可逆的,但它不是UTF,因为依赖于不同的SCSU压缩器,同样的字符串可以映射到多个不同的字节序上。

7

Page 8: Utf和bom的常见问题

Q:有哪些字节序不是由UTF生成的?如何表示它们?

• A:所有的UTF都无法生成任意的字节序。例如,在UTF-8中每个形如110xxxxx的字节序必须紧跟形如10xxxxxx的字节序。例如<110xxxxx0xxxxxxx>是非法的,不应该被生成。当在转换或翻译时,遇到这个非法字节序,UTF-8一致性处理“必须”将第一个字节序110xxxxx当作终止错误:例如,要么发送错误信号,要么过滤掉该字节序,或者要么用如FFFD(REPLACEMENT CHARACTER)这样的标记符替代该字节序。而后两者,它将继续处理第二个字节序0xxxxxxx。

• 一致性处理“必须”不能将非法或病态的字节序翻译成字符,但是,它可能采取错误恢复措施。任何一致性处理都不会使用不规则的字节序来编码带外数据。

8

Page 9: Utf和bom的常见问题

Q:应该支持哪些UTF编码形式?

• A:UTF-8在web上普遍使用。UTF-16在Java和Windows系统中使用。UTF-8和UTF-32在很多Linux和Unix系统中使用。它们之间的

转换是基于快速、无损的算法的。这使得

内部存储或处理仅使用一种专有的UTF编

码,同时又支持多种编码形式的数据的输

入输出变得非常容易。

9

Page 10: Utf和bom的常见问题

Q:各种UTF编码之间的区别是什么?

• A:如下表格总结了各种UTF编码的一些属

性。表中<BOM>表示字节序由一个字节序

标记决定的。它在数据流的头部给出,否

则为big-endian。

名字 UTF-8 UTF-16 UTF-16BE UTF-16LE UTF-32 UTF-32BE UTF-32LE

最小编码点 0000 0000 0000 0000 0000 0000 0000

最大编码点 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF

单位编码大

小8 bits 16 bits 16 bits 16 bits 32 bits 32 bits 32 bits

字节序 N/A <BOM> big-endian little-endian <BOM> big-endian little-endian

每字符最少

字节数1 2 2 2 4 4 4

每字符最多

字节数4 4 4 4 4 4 4

10

Page 11: Utf和bom的常见问题

Q:有没有标准的方法来包装一个Unicode字符使其符合8位ASCII流?

• A:4个建议让Unicode符合8位格式。• a)使用UTF-8。它保留了ASCII而非Latin-1,因为字符>127时和Latin-1不一致。

UTF-8仅仅为ASCII字符使用ASCII中的字节。因此,在用ASCII字符作为语法字符的任何重要环境中都表现不错,举例如,文件名、标记语言等等,但是所有其他字符可能使用任意的字节。例如:“Latin小字母s急性”(015B)会被编码为2字节:C59B。

• b)使用Java或C的转义风格:\uXXXXX或\xXXXXX。这些格式在文本文件中是非标准的,但在上面谈到的语言框架下有良好的定义,主要就是针对源文件。例如:波兰语“wyjście”中间使用了“Latin小字母s急性”(015B)编码后看起来是这样的:“wyj\u015Bcie”。

• c)在HTML或XML中使用&#xXXXX;或&#DDDDD;这样的数字字符转义风格。同样,这些格式在文本文件中是非标准的,但在这些标记语言框架下有良好的定义。例如:“wyjście”编码后看起来是这样的:“wyj&#x015B;cie”。

• d)使用SCSU。这种格式将Unicode压缩为8位格式,保留大多数ASCII字符,但用一些控制码作为解码命令。尽管ASCII文本在SCSU编码后看起来还是ASCII文本,但是,有些字符可能偶尔会被编码为相同的字节值,它盲目地翻译任意字节值为ASCII字符,这使得SCSU不适合8位通道。例如:“<SC2> wyjÛcie”中,<SC2> 表示字节0x12,“Û”对应的字节0xDB。

11

Page 12: Utf和bom的常见问题

Q:上述方法哪种最好?

• A:这个问题依赖实际的环境:4种方法

中,d)使用空间最少,但不能在大多数8位环境中透明地使用。a)在文本文件中得到最广泛地支持。b)和c)使用空间最多,

但在Java和C或者HTML和XML程序源文件中各自得到了广泛地支持。

12

Page 13: Utf和bom的常见问题

Q:上述哪种格式最标准?

• A:所有4种方法都要求接收方能够理解这

些格式,但a)被认为是三个等效的Unicode编码形式之一,因此就是标准。在给定的

上下文环境之外使用b)或c),很明确是非标准的,但是它也是内部数据传输很好的

解决方案。使用SCSU本身是一种标准(针

对压缩数据流),但很少有通用目的的接

收方支持SCSU,故它也只是在内部数据传

输中很有用而已。

13

Page 14: Utf和bom的常见问题

涉及UTF或

编码形式的

一般性问题

UTF-8的常

见问题

UTF-16的常

见问题

UTF-32的常

见问题

BOM的常

见问题

14

Page 15: Utf和bom的常见问题

UTF-8的常见问题

Q:什么是UTF-8?

Q:UTF-8编码方案也如同基本处理器一样与是否是little-endian或big-endian是无关的吗?

Q:UTF-8编码方案也如同基本系统一样与是否使用ASCII或EBCDIC编码是无关的吗?

Q:如何将一个UTF-16成对的代理如<D800 DC00>转换为UTF-8?是1个4字节序列还是2个3字节

序列?CII或EBCDIC编码是无关的吗?

Q:如何将UTF-16不成对的代理转换为UTF-8?

15

Page 16: Utf和bom的常见问题

Q:什么是UTF-8?

• A:UTF-8是Unicode中面向字节的编码形式。详细的定义,见Unicode标准的2.5节“编码形式”和3.9节“Unicode编码形式”。特别要看一下表3-6的 “UTF-8 位分布”和表3-7的“良好编码的UTF-8字节序”,它们是编码形式的简明扼要的总结。因为随着时间的推移Unicode技术委员会已经对UTF-8加固了定义,使得它成为更加严格而唯一的序列并且禁止了某些非法字符的编码形式,故,确保你参考的是最新版本的Unicode标准。关于UTF-8有个互联网RFC3629。UTF-8还在ISO/IEC10646的附录D中有定义。同时,请参见上面的常见问题:如何写一个UTF转换器?

16

Page 17: Utf和bom的常见问题

Q:UTF-8编码方案也如同基本处理器一样与是否是little-endian或big-endian是无关的吗?

• A:是的。既然UTF-8作为字节的序列来解

释,那么它没有字节排列顺序的问题,这

些问题会在使用16位或32位编码单元中会

出现。UTF-8使用BOM只是为了标记以区别

于其他编码形式——与字节序本身无关。

17

Page 18: Utf和bom的常见问题

Q:UTF-8编码方案也如同基本系统一样与是否使用ASCII或EBCDIC编码是无关的吗?

• A:UTF-8只有一个定义。数据无论从基于

ASCII或EBCDIC字符集转换而来,两者之间

都是严格一致的。然而,标准UTF-8的字节

序与EBCDIC系统的互通性不好,因为ASCII和EBCDIC的控制码布置是不一样的。

Unicode技术报告#16:UTF-EBCDIC定义了一

个特殊的UTF,它能够与EBCDIC系统互通。

18

Page 19: Utf和bom的常见问题

Q:如何将一个UTF-16成对的代理如<D800 DC00>转换为UTF-8?是1个4字节序列还是2个3字节序列?

• A:UTF-8的定义要求辅助字符(在UTF-16中使用成对的代理)按照单个4字节序列编码。但是,在老式的软件中有一种广泛实践过的生成3字节序列对的方法,特别是那些软件在UTF-16引入之前的时期,或者是与UTF-16有互通的在特殊限制的环境下。这种编码和UTF-8的定义是不一致的。见UTR #26:UTF-16的8位兼容编码方案(CESU),这是对非UTF-8数据格式的正式描述。使用CESU-8要特别小心,数据不是因为格式相似而意外地被当作UTF-8的。

19

Page 20: Utf和bom的常见问题

Q:如何将UTF-16不成对的代理转换为UTF-8?

• 如果在转换病态的UTF-16数据时遇到不成对

的代理,会产生不一样的问题。通过将这

种自身不成对的代理表示为3字节的序列,

由此产生的UTF-8数据流是病态的。当转换

器忠实地反应输入的本质时,Unicode一致性要求编码形式转换生成的数据流总是合

法的。因此,转换器“必须”将其作为错误对

待。

20

Page 21: Utf和bom的常见问题

涉及UTF或

编码形式的

一般性问题

UTF-8的常

见问题

UTF-16的常

见问题

UTF-32的常

见问题

BOM的常

见问题

21

Page 22: Utf和bom的常见问题

UTF-16的常见问题

Q:什么是UTF-16?

Q:什么是代理?

Q:为什么有些人反对UTF-16?

Q:UTF-16会扩展到超过一百万的字符吗?

Q:哪些16位值是非法的?

Q:因为辅助字符不常见,是否意味着可以忽略它们?

Q:在代码中如何处理辅助字符?

22

Page 23: Utf和bom的常见问题

Q:什么是UTF-16?

• A:UTF-16使用单个16位编码单元来编码最常用的63k个Unicode字符,使用一对16位编码单元(称作代理)来编码1M个不太常用的Unicode字符。

• 最初,Unicode设计为一个单纯的16位编码,目的在于表示所有的现代稿件。(过时的稿件被表示为私有使用的字符。)随着时间的推移,特别是在增加了145000复合字符来兼容遗留的字符集后,16位显然是不够的。出于这种考虑产生了UTF-16。

23

Page 24: Utf和bom的常见问题

Q:什么是代理?

• A:代理是在两个特殊的Unicode值的范围内

编码点,它们保留作前导和拖尾使用,构

成了成对的UTF-16编码单元。前导,也称作

高位,代理编码从D800到DBFF。拖尾,也称作低位,代理编码从DC00到DFFF。因为

它们不直接表示字符,所以称为代理,但

成对出现。

24

Page 25: Utf和bom的常见问题

Q:为什么有些人反对UTF-16?

• A:人们熟悉的可变宽度的东亚字符集,如为Shift - JIS(SJIS),有时需要两个编码单元表示单个字符,可以理解这让人对UTF-16很担心。他们非常熟悉可变宽度编码造成的问题。但是,UTF-16与SJIS中使用的机制有一些很重要的不同:

• 重叠:• 在SJIS中,前导与拖尾编码单元值之间是有重叠的,拖尾与单个编码单元值之间也是。这导

致了一些问题:– 匹配错误。例如,在拖尾编码单元中查找“a”可能是一个日本文字符。– 失去了随机访问的高效。为了知道是否在字符范围内,不得不后向搜索找到边界。

– 让文本非常脆弱。假如一个单元从前导-拖尾编码单元中丢失,紧随其后的很多字符也随之损坏。

• 在UTF-16中,高位和低位代理编码点范围和单个编码单元一样都是完全不相交的。下面的问题都不会产生:– 匹配错误。There are no false matches.– 从每个编码单元值中,字符边界位置能直接确定。

• 丢失代理编码仅导致单个字符损坏。• 频率:

• 绝大多数SJIS字符需要2个编码单元,但是单个编码单元的字符非常常见并尤其重要,例如文件名。

• 用UTF-16,相对较少的字符需要2个编码单元。绝大多数常见的字符是单个编码单元的。甚至在东亚字文字中,病态代理对几率应该在文本存储平均值的1%以下。当然,某些文档可能病态代理对的几率较高,就像“phthisique ”尽管在英文中的频率不高,但在特殊的学术文章中经常出现的一样。

25

Page 26: Utf和bom的常见问题

Q:UTF-16会扩展到超过一百万的字符吗?

• A:不会。Unicode和ISO10646都有策略来正式限制未来分配的编码在UTF-16能表示的整数范围内(0 到1114111)。甚至如果其他编码形式(例如,其他UTF)能表示更大的整数,这些策略意味着所有的编码形式总是表示相同的字符集。超过百万的编码远远大于满足容纳Unicode编码字符的目标,当然不是针对字形。Unicode不是设计用来编码任意数据的。例如,想要将“整个历史上在纸上出现过的所有字符实例”都要赋予它自己单独的编码,那恐怕需要万亿或百万亿计的编码;这种努力是高尚,但是可能不会有人使用这样的Unicode编码。

26

Page 27: Utf和bom的常见问题

Q:哪些16位值是非法的?

• A:FFFE、FFFF和从FDD0到FDEF的32个值

(译注:共34个)表示非字符。在数据交换时它们是非法的,但可以在一中实现在

内部自由使用。不成对的代理也是非法

的,任何D800到DBFF范围的值后面没有紧

跟DC00到DFFF范围的值。

27

Page 28: Utf和bom的常见问题

Q:因为辅助字符不常见,是否意味着可以忽略它们?

• A:只是由于辅助字符(在UTF-16中表示为成对的代理)不常见,而不是意味着它们可以被忽视。它们包含:

• 和日本移动电话互通的绘图文字和表情符号

• 不常见(但不是不用)的CJK字符,对于人名和地址很重要

• 表意文字变化序列的变化选择器

• 重要的数学符号• 数量众多的少数名族和历史性的稿件,对有些用户群体很重要

28

Page 29: Utf和bom的常见问题

Q:在代码中如何处理辅助字符?

• A:和BMP字符相比,在大多数上下文中辅

助字符相对不常见。当要为了最佳性能而

优化实现时,这个事实可以考虑进去:执

行速度、内存用量和存储空间。对UTF-16的实现来说这特别有用,在UTF-8的实现中程

度较轻。

29

Page 30: Utf和bom的常见问题

涉及UTF或

编码形式的

一般性问题

UTF-8的常

见问题

UTF-16的常

见问题

UTF-32的常

见问题

BOM的常

见问题

30

Page 31: Utf和bom的常见问题

UTF-32的常见问题

Q:什么是UTF-32?

Q:在内存中Unicode字符串排序应该使用UTF-32(UCS-4)吗?

Q:在API中使用UTF-32的接口会如何?

Q:API中只使用字符串参数的规则是否有例外?

Q:如何将UTF-16成对的代理如<D800 DC00>转换到UTF-32中?是1个

4字节序列还是2个4字节的序列?

Q:如何将UTF-16不成对的代理转换到UTF-32中?

31

Page 32: Utf和bom的常见问题

Q:什么是UTF-32?

• A:在UTF-32中,任何Unicode字符都可以表示为单个32位编码单元。该4字节的编码单

元对应于Unicode标量值,它是一个关联到

Unicode字符的抽象数字。UTF-32是ISO10646编码机制的子集,称作UCS-4。详

细的信息参见Unicode标准的3.9节:“Unicode编码形式”。

32

Page 33: Utf和bom的常见问题

Q:在内存中Unicode字符串排序应该使用UTF-32(UCS-4)吗?

• A:看情况。如果需要经常访问的API字符串参数要求UTF-32形式,那始终使用UTF-32字符串比较方便。但缺点就是迫使每个字符都是32位的,事实上只需要21位。在普通的文本中平均使用高位数字的字符很少,这使得有效比例非常低。在很多情况下这无所谓,每个字符拥有固定数量的编码单元带来的便利起到了决定性的作用。

• 同样数量的字符却增加了不少存储空间确实对应用程序处理大容量的文本数据时一种浪费:这意味着更早到达缓存上限;明显增加读/写次数或达到带宽上限;需要更多的存储空间。有一些实现是这样做的:字符串使用UTF-16,单个字符是UTF-32,下面有个例子。

• Unicode的主要卖点就是提供了表示世界上所有字符的方法,消除了使用各种字符集的需要,并避免了相关数据损坏的问题。这些特性足矣让整个行业都趋于使用Unicode(UTF-16)。尽管UTF-32的表示确实让编程模型有一定程度上的简化,平均存储空间的增加也确实个缺点,全部转换成UTF-32并非引人注目。

33

Page 34: Utf和bom的常见问题

Q:在API中使用UTF-32的接口会如何?

• A:除了有些环境以UTF-32在内存中存储文

本,大多数Unicode API使用UTF-16。使用UTF-16的API,底层索引是在存储或编码单

元级别的。对于字形或单词是在更高的级

别机制中在编码单元上指定了它们的边界。

这提供了底层的效率,并保证了高层的功

能。

• 注:此处有删节,请参看英文原稿。

34

Page 35: Utf和bom的常见问题

Q:API中只使用字符串参数的规则是否有例外?

• A:最大的例外是例如获得字符属性(也就

是说UCD中通用分类或规范类)这种底层操

作。对于这些,有方便的接口与UTF-16和UTF-32之间互相转换,也允许遍历字符串并

返回UTF-32的值(即使它的内部格式是UTF-16的)。

35

Page 36: Utf和bom的常见问题

Q:如何将UTF-16成对的代理如<D800 DC00>转换到UTF-32中?是1个4字节序列还是2个4字节的序列?

• A:UTF-32的定义要求辅助字符(在UTF-16中使用成对的代理)应该编码成单个4字节

的序列。

36

Page 37: Utf和bom的常见问题

Q:如何将UTF-16不成对的代理转换到UTF-32中?

• A:如果在转换病态的UTF-16数据时碰到不

成对的代理,任何一致性转换器必须视之

为错误。如若将这些不成对的代理表示为

UTF-32的数据,它们是病态的。虽然它忠实

地反映输入的本质,Unicode的一致性要求编码形式转换始终生成有效的数据流结

果。

37

Page 38: Utf和bom的常见问题

涉及UTF或

编码形式的

一般性问题

UTF-8的常

见问题

UTF-16的常

见问题

UTF-32的常

见问题

BOM的常

见问题

38

Page 39: Utf和bom的常见问题

BOM的常见问题

Q:什么是BOM?

Q:BOM在哪里非常有用?

Q:“endian”是什么意思?

Q:是否只在16位Unicode文本中使用BOM?

Q:UTF-8数据流可以包含BOM(以UTF-8形式)吗?如果是,是否

仍然可以认为其他UTF-8字节是big-endian字节序的呢?

Q:为什么不一直使用需要BOM的协议?

Q:应该如何处理BOM?39

Page 40: Utf和bom的常见问题

Q:什么是BOM?

• A:字节序标记(BOM)是在数据流的开头

包含U+FEFF的编码,那里可以用来定义字

节序和编码形式,主要是常规的明文文

件。在一些高级协议中,会明确定义在

Unicode数据流中使用BOM是强制的(或是

禁止的)。

40

Page 41: Utf和bom的常见问题

Q:BOM在哪里非常有用?

• A:在输出为文本的文件的开头使用BOM,它指示文件是big-endian或是little-endian——它还能指示文件是Unicode,因为它不在

传统的编码中,而是可以作为一个使用特

定编码形式的签名。

41

Page 42: Utf和bom的常见问题

Q:“endian”是什么意思?

• A:计算机内存中可以存储长度大于1字节的数据,只是选择高位(MSB)在前还是在后的问题。前者称作big-endian,后者称作little-endian。进行数据交换时,在发送端系统中的字节看似顺序“正确”也许在接收端系统中顺序“错乱”。在这种情况下,BOM看上去像0xFFFE的非字符,使得接收系统在处理数据之前先应用字节逆转。UTF-8是面向字节的,因此没有这个问题,然而,开头的BOM有助于鉴别数据流是否是UTF-8的。

42

Page 43: Utf和bom的常见问题

Q:是否只在16位Unicode文本中使用BOM?

• A:不是。BOM用作签名使用,无论

Unicode文本采用什么编码形式:UTF-16、UTF-8或UTF-32。用某种格式转换Unicode字符U+FEFF得到了一些确定的字节,这就是

BOM。以那种形式,BOM不仅指示了文件

是Unicode,而且表示了特定的格式。例如:数据 编码形式

00 00 FE FF UTF-32, big-endian

FF FE 00 00 UTF-32, little-endian

FE FF UTF-16, big-endian

FF FE UTF-16, little-endian

EF BB BF UTF-8 43

Page 44: Utf和bom的常见问题

Q:UTF-8数据流可以包含BOM(以UTF-8形式)吗?如果是,是否仍然可以认为其他UTF-8字节是big-endian字节序的

呢?

• A:是的,UTF-8可以包含BOM。但是,不同的字节序系统对字节流没有影响。UTF-8总是有相同的字节顺序。开头的BOM只是用来签名——指示被标记的文件是UTF-8。注意,有些UTF-8解码器不希望接收BOM。若在8位环境中要透明地使用UTF-8,使用BOM会干扰那些格式期望在开头处有特定

的ASCII字符的协议或文件,例如在Unix的shell脚本在文件开头使用“#!”。

44

Page 45: Utf和bom的常见问题

Q:为什么不一直使用需要BOM的协议?

• A:在数据有关联类型的地方,如数据库的字段,BOM是没有必要的。特别地,如果文本数据流标记为UTF-16BE、UTF-16LE、UTF-32BE或者UTF-32LE,BOM既不需要也不允许。任何U+FEFF都会被翻译为ZWNBSP 。

• 不要将数据库或字段集合中的每个字符串都用BOM来标记,因为这既浪费空间,又让字符串连接变得更加复杂。其次,这意味着两个数据字段可能有一样的内容但在二进制下不相等(可能其一是由BOM开始的)。

45

Page 46: Utf和bom的常见问题

Q:应该如何处理BOM?

• A:以下有几条建议:

• 一个特定的协议(例如,微软惯用的.txt文件)可能要求在数据流上(如文件),使用BOM。当需要去遵循这样的协议时使用BOM。

• 有些协议在未标记文本的情况下允许BOM是可选的。这些情况,– 已经知道文本数据流是纯文本,但不知道编码形式,BOM可以用

作签名。如无BOM,编码形式可能是任意的。

– 已经知道文本数据流是纯Unicode文本,但不知道字节序,BOM可以用作签名。如无BOM,文本应该被看作big-endian。

• 有些面向字节的协议期望在文件开头是ASCII字符。如果这些协议使用UTF-8,那就应该避免使用BOM作为编码形式的签名。

• 在知道数据流的精确类型的地方(例如,Unicode的big-endian或little-endian),不应该使用BOM。特别地,无论何时数据流申明为UTF-16BE、UTF-16LE、UTF-32BE或者UTF-32LE,禁止使用BOM。(参看Q:UCS-2与UTF-16之间的区别是什么?)

46

Page 47: Utf和bom的常见问题

Thanks!47