源代码文件的编码往往被忽略, 多数情况下它们也不引起什么问题, 一般来说, 在简体中文的OS上, 如果你输入了汉字, 是按Code Page代码页指定的编码来保存文件, 也就是GB2312, 或说CP936.
但也有如下一些情况让你不得不注意编码问题:
情况一: 在C#源文件中, GB2312 编码时, 个别的汉字会引起 Resharper这样的解析工具崩溃. 这个问题费了我很大周折才找出来, 原因是特定的汉字组合造成的. 这在希望写中文注释的情况就有些危险.
情况二: 在C#源文件中, 希望用汉字之外的其它字符, 典型的情况是, 使用 Attribute在编码期就指定一些字符串, 比如我自己的C#常用类库中就定义了这样的一些Attribute, 用于指定某个与UI相关的项如Enum在各种语言下的Localize string. 这种情况没得跑了, 得用Unicode.
情况三: 即使在C++源文件中, 混入汉字的注释, 会在与其它工具交互时出错, 这个问题只是模糊印象, 曾经碰到过问题, 记不得具体的情形了.
鉴于这些情况, 我在项目中做了以下的修改:
1. 一次性修改项目中所有文件中涉及ASCII之外的字符的源文件的编码, 统一为UTF-8
2. 由于VS IDE不能正确处理不包含BOM(byte order mark)的UTF-8源文件, 所以还得保证BOM
3. 对于大多数仅包含ASCII的文件, 不需要改动什么, 但在提交任何一个文件时, 检查其是否GB2312编码, 如果是, 则说明含有非ASCII字符, 拒绝check in, 给出提示建议, 如果是UTF-8编码, 但没有BOM, 同样拒签, 给出提示建议.
乍想简单, 实际操作中让我碰到不少问题:
1. 怎么检测文件编码. 用cygwin/file 命令, 这涉及到从cygwin 中摘取file.exe工具和它所依赖的DLL, copy到CVS服务器上运行, depends 是有力的工具.
2. file.exe 命令要正确运行, 除了依赖的DLL外, 还得有个运行时的数据文件. 里面保存着各种文件的特征描述, 这个问题有另文记述.
3. 检查file对不同编码文件的输出, 分析其特征, 找出哪些是仅含ASCII字符, 哪些是格式非法的文件.
比如, 对于GB2312编码, 它并不输出GB2312 的字样, 而是ISO-8859. 而如果文件仅含有ASCII字符, 则总是识别为ASCII文件.
Regex re_encoding = new Regex(@":\s*\bISO-8859\b");
符合这样正则式的是疑似GB2312 编码的文件.
4. 检测是Unicode 但不是UTF-8编码的情况:
file的输出中含有 "Unicode", 但不是"UTF-8 Unicode"
5. 如果是UTF-8编码, 检查是否含有BOM:
读取文件的前三个字节, 检查是否为 0xef, 0xbb, 0xbf
6. 例外. DRY原则下, 我们的项目与另一个嵌入式小组的项目共享同一个头文件, 该文件中也含有汉字, 但当这个文件被转为BOMed UTF-8 encoding时, 另一个项目组的人跳了起来, 他们使用Keil 编译器, 不能处理UTF-8编码的文件, 所以这个文件不得不被当作一个特例放行.
file.exe 的典型输出包括:
ASCII C program text, with CRLF line terminators
ASCII C++ program text
ASCII C++ program text, with CRLF line terminators
ASCII C++ program text, with very long lines, with CRLF line terminators
ASCII English text, with CRLF line terminators
ASCII text, with CRLF line terminators
Non-ISO extended-ASCII C program text, with CRLF line terminators
UTF-8 Unicode C program text, with CRLF line terminators
UTF-8 Unicode C program text, with CRLF, CR line terminators
UTF-8 Unicode C program text, with very long lines, with CRLF line terminators
UTF-8 Unicode C++ program text
UTF-8 Unicode C++ program text, with CRLF line terminators
UTF-8 Unicode C++ program text, with very long lines, with CRLF line terminators
UTF-8 Unicode English text, with CRLF line terminators
UTF-8 Unicode text, with CRLF line terminators
XML document text
下图是实际使用时的效果, 检测到是UTF-8编码, 但没有BOM
阅读(1507) | 评论(0) | 转发(0) |