Microsoft的集成开发环境(IDEs),源文件编码,字节顺序标记(BOM)以及Unicode字符\uFEFF?

3
我们有各种Microsoft语言的解析器(VB6,VB.net,C#,MS C/C++方言),它们都启用了Unicode,只要我们都认可Unicode。在我们不同意的情况下,我们的词法分析器会发出警告。
最近的MS IDE似乎都将源代码文件读/写为UTF-8格式……但我不确定这总是正确的。是否有一些参考文献明确说明MS如何编写源代码文件?带或不带字节顺序标记(BOM)?IDE版本是否有所不同?(我无法想象旧版VB6开发环境写的文件使用的字符集以外的东西,我猜它会使用由区域设置所确定的CP-xxxx编码,对吗?)
对于C#(以及我认为由MS支持的其他现代语言方言),字符码“\uFEFF”实际上可以在文件中间找到。此代码定义为零宽度不换行空格。当在标识符中间和空白处时,VS 2010似乎忽略它,但在关键字和数字中具有重要意义。那么规则是什么?或者MS是否有某种规范化标识符的方式来处理诸如复合字符之类的内容,从而允许将不同的标识符字符串视为相同?

从你的问题中不清楚你的东西是否符合语言规范...例如,我相信C#默认是UTF-16。 - Factor Mystic
UTF-8和UTF-16除了字符存储方式不同以外并没有太大区别。通过VS2010的直接实验可以发现,保存新文件会得到一个UTF8文件,并且在读取没有BOM的文件时,IDE会默认认为字符编码是UTF-8。是的,我们的东西符合语言规范,在我们有一个好的语言定义的情况下。我想知道这个是否存在,如果存在的话在哪里可以找到,如果不存在,人们实际上了解什么。 - Ira Baxter
关于UTF-8,我们的工具会根据文件的“表面”或声明的编码来读取文件,并在读取时将字符内部转换为UTF-16。因此,我们的C#解析器只能看到UTF-16字符。当各种IDE生成的文件没有特定的字节顺序标记时,我们很难知道它们的编码是什么。我们也遇到了在文件中间发现的代码点\FEFF的问题。 - Ira Baxter
3个回答

4
这在某种程度上是一个非答案,因为它没有告诉我们微软的说法,而是告诉我们标准的说法。希望这仍然能够有所帮助。

U+FEFF作为常规字符

正如您所述,U+FEFF应该被视为文件开头的BOM(字节顺序标记)。理论上,它也可以出现在文本中间,因为它实际上是表示零宽度不换行空格(ZWNBSP)的字符。在某些语言/书写系统中,一行中的所有单词都连接在一起(=写在一起),在这种情况下,该字符可以用作分隔符,就像英语中的常规空格一样,但它不会造成印刷上可见的间隙。我实际上并不熟悉这样的脚本,因此我的看法可能不完全正确。

U+FEFF只应出现为BOM

然而,自Unicode版本3.2起,将U+FEFF用作ZWNBSP的用法已被弃用,目前U+FEFF的目的是作为BOM。Unicode联盟强烈建议使用U+2060(单词连接器)字符作为分隔符,而不是ZWNBSP。他们的常见问题解答还建议,在文件中间出现的任何U+FEFF都可以视为不受支持的字符,应显示为不可见。我想到的另一个可能的解决方案是将文件中间出现的任何U+FEFF替换为U+2060或忽略它。

意外添加U+FEFF

我认为U+FEFF出现在文本中间的最有可能的原因是它是字符串连接的错误结果(或副作用)。RFC 3629,该文档纳入了BOM的使用,指定在连接字符串时需要去除前导的U+FEFF。这也意味着在文本中间找到该字符时可以将其删除。

U+FEFF和UTF-8

U+FEFF作为BOM在UTF-8编码时没有实际效果,因为它始终具有相同的字节顺序。在UTF-8中使用BOM会干扰依赖特定前导字符存在的系统和明确规定编码或编码识别方法的协议。实际经验还表明,一些应用程序无法处理带有BOM的UTF-8。因此,在使用UTF-8时通常不建议使用BOM。从UTF-8编码的文件中删除BOM不应该导致文件被错误解释(除非与文件的字节流相关的某个校验和或数字签名)。

1
关于“MS将如何编写源代码文件”的问题:VS可以保存带有或不带BOM的文件,以及其他许多编码方式。默认设置为带有BOM的UTF-8。您可以通过转到“文件”->“另存为”->单击“保存”按钮上的三角形并选择“使用编码保存”来尝试它。
关于实际代码中使用FEFF - 从未见过在代码中使用它的情况...维基百科建议如果在第一个位置之外出现,则应将其视为零宽度空格(http://en.wikipedia.org/wiki/Byte_order_mark)。

当然,这就是维基百科所说的。但是它非常模糊,"将其视为零宽度空格"是什么意思?我想知道微软的说法,包括章节和经文的引用。 - Ira Baxter

0
对于C++,文件是Unicode带BOM,或将被解释为ANSI(意味着系统代码页,不一定是1252)。是的,您可以使用任何编码保存,但如果您尝试在系统代码页为1252的操作系统上编译Shift-JIS文件(日语,代码页932),则编译器将会出错。
事实上,即使编辑器也会出现问题。您可以在1252系统上保存Shift-JIS格式,看起来还不错。但是关闭项目并重新打开它,文本看起来就像垃圾一样。因此,信息无处可保存。
所以这是您最好的猜测:如果没有BOM,请假定为ANSI。这就是编辑器/编译器所做的。
另外:VS 2008和VS 2010是较旧的编辑器,不支持Unicode。 C++有不同的规则,与C#不同(对于C++,默认情况下文件为ANSI,对于C#,它们是UTF-8)。

“Unicode带BOM”是什么意思?UTF-8、UTF-16和UTF-32都是Unicode的表示形式。(将“ANSI”误用于指代Windows特定的代码页使我怀疑您指的是UTF-16,但很难确定。) - Keith Thompson
“Unicode with BOM”指的是带有BOM的UTF-16和UTF-8(Windows不支持UTF-32,甚至不支持转换)。是的,UTF-8的BOM不起到BOM的作用,而是起到“编码标记”的作用。对于“ANSI代码页”,似乎被误用了,但这不是我的误用,这是Windows术语。Windows使用“ANSI代码页”来表示“当前系统代码页”(因此,即使是932,日本代码页,也可以是“ANSI代码页”)。这确实是一个错误的命名,但这不是我的错。 - Mihai Nita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接