2010-07-25 137 views
3
  1. 为什么保存为UTF8(在Notepad ++中)的文件在fstream的开头有这个字符我在C++程序中打开它?C++ ifstream UTF8第一个字符

    '╗┐

    我不知道它是什么,我只知道,它不存在,当我保存到ASCII。 更新:如果我将它保存到UTF8(没有BOM),它不在那里。

  2. 如何在C++中检查文件的编码(ASCII或UTF8,其他所有内容将被拒绝;))。这正是这些人物吗?

谢谢!

+0

你可以给我们一个十六进制转储的文件的开头,而不是我们不认识的几个随机字符(并且我们的字体可能不会显示?) – 2010-07-25 15:53:14

+1

它可能是一个UTF-8 BOM误解作为IBM850。 – dan04 2010-07-26 04:39:43

回答

7

当您将文件另存为UTF-16时,每个值都是两个字节。不同的电脑使用不同的字节顺序一些首先放置最重要的字节,一些首先放置最不重要的字节。 Unicode保留一个称为字节顺序标记(BOM)的特殊码点(U + FEFF)。当一个程序用UTF-16编写一个文件时,它将这个特殊的代码点放在文件的开头。当另一个程序读取一个UTF-16文件时,它知道应该有一个BOM。通过将实际字节与预期BOM进行比较,可以判断读者是否使用与写入器相同的字节顺序,或者是否必须交换所有字节。

保存UTF-8文件时,字节顺序没有歧义。但是一些程序,尤其是为Windows编写的程序仍然添加一个BOM,编码为UTF-8。将BOM代码点编码为UTF-8时,会得到三个字节,0xEF 0xBB 0xBF。这些字节对应于大多数OEM代码页中的框图字符(这是Windows上的控制台窗口的默认字符)。

赞成这样做的理由是它将文件标记为真正的UTF-8,而不是其他本地编码。例如,西方Windows上的许多文本文件都在代码页1252中。使用UTF-8编码的BOM标记文件可以更容易地区分差异。

反对这样做的观点是很多程序期望ASCII或UTF-8无论如何,也不知道如何处理额外的三个字节。

如果我正在编写一个读取UTF-8的程序,我会在开始时检查这三个字节。如果他们在那里,跳过他们。

更新:您可以将U+FEFF ZERO WIDTH NO BREAK字符转换为U+2060 WORD JOINER [吉勒姆,理查德,统一揭秘除了在文件的开头,Addison-Wesley出版社,2003,页。 108]。我的个人代码这样做。如果在解码UTF-8时,我在文件开头看到0xEF 0xBB 0xBF,我认为它确实是UTF-8。如果文件不是以这些字节开头的,我只是正常解码。如果在文件稍后解码时遇到U + FEFF,则发出U + 2060并继续。这意味着U + FEFF仅用作BOM,而不是其不推荐的含义。

+1

“反对这样做的观点是很多程序都希望使用ASCII或UTF-8,并且不知道如何处理额外的三个字节。”我没有关注。 'EF BB BF'是UTF-8,代表一个零宽度,非破坏性的空间 - 基本上意味着“没有”,这就是选择BOM的原因。如果一个程序读取UTF-8,它必须能够读取这个字符并知道如何处理它。 – sbi 2010-07-25 16:08:00

+0

它比这强得多。不允许在UTF编码文件中省略BOM。由于显而易见的原因,读取该文件的程序将不能猜测它包含UTF编码文本。 – 2010-07-25 16:16:22

+1

@Hans:TTBOMK,BOM始终是可选的,从不需要。 – sbi 2010-07-25 16:29:14

1

为什么保存为UTF8 文件必须在开始这个人物[...]我不知道它是什么,我只知道,它不存在,当我保存到ASCII。

我想你指的是字节顺序标记(BOM)U+FEFF,一个零宽度,不间断的空格字符。这里(记事本++ 5.4.3)保存为UTF-8的文件在开头处具有字符EF BB BF。我想这就是用UTF-8编码的物料清单。

我如何检查文件

你不能的编码。你必须知道什么编码你的文件被写入。虽然Unicde编码文件可能开始与物料清单,我不认为有要求,他们这样做。

0

我猜你的意思是问,为什么它有这些字符。这些字符可能是byte order mark,根据UTF-8中的链接,字节EF BB BF。

至于知道什么编码文件是在,你不能从文件本身得到。你必须提前知道它(或询问谁提供你的文件)。为了更好地理解编码而不必进行大量阅读,我强烈建议Joel Spolsky的The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

+1

引用维基百科作为参考是一种不好的做法,你应该打破http://en.wikipedia.org/wiki/Wikipedia:Citing_Wikipedia。维基百科是开始研究和寻找权威参考的好点,但它绝不应该被用作参考,因为它具有无法验证的作者身份,也不知道作者无法知道他们评论的质量或准确性。该wiki文章中提到了一个更好的参考资料,指向官方的Unicode网站:http://www.unicode.org/faq/utf_bom.html – 2010-07-25 16:50:03

+0

一个很好的观点。我已经相应地修改了我的答案。 – SCFrench 2010-07-25 18:10:43

0

不知道这些字符真正是什么(即没有十六进制转储),这只是一个猜测,但我的直接猜测是,你看到的是一个字节顺序标记(BOM)和( )编码为UTF-8。从技术上讲,你不能/应该这样做,但在实践中,它实际上是相当普遍的。

只是为了澄清,你应该认识到,这个不是真的是一个字节顺序标记。字节顺序标记的基本概念不适用于UTF-8。理论上,UTF-8编码绝不应该应用于物料清单 - 但您可以忽略它,并将正常的UTF-8编码规则应用于构成物料清单的值(如果需要)。

+1

有点强烈的说”UTF-8编码永远不应该应用于BOM ”。将它用于字节排序是多余的,但它作为编码签名是可以允许的。请参阅http://unicode.org/faq/utf_bom.html#bom5 – 2010-07-25 19:48:44

1

关于第二点,每个有效的ASCII字符串也是有效的UTF-8字符串,因此您不必显式检查ASCII。只需使用UTF-8读取文件,如果文件不包含有效的UTF-8字符串,则会出现错误。