【问题标题】:C++ ifstream UTF8 first charactersC++ ifstream UTF8 第一个字符
【发布时间】:2011-03-20 18:42:06
【问题描述】:
  1. 为什么保存为 UTF8(在 Notepad++ 中)的文件在我在 c++ 程序中打开的 fstream 开头有这个字符?

    ´╗┐

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

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

谢谢!

【问题讨论】:

  • 你能给我们一个文件开头的十六进制转储,而不是一些我们无法识别的随机字符(而且我们的字体可能不会显示吗?)
  • 可能是 UTF-8 BOM 被误解为 IBM850。

标签: c++ utf-8 ascii fstream byte-order-mark


【解决方案1】:

为什么保存为UTF8的文件没有开头有这个字符[...]我不知道它是什么,我只知道它不是当我保存为 ASCII 时。

我想您指的是字节顺序标记 (BOM) U+FEFF,一个零宽度、不间断的空格字符。这里(notepad++ 5.4.3)保存为 UTF-8 的文件,开头有字符 EF BB BF。我想这就是用 UTF-8 编码的 BOM。

如何检查文件的编码

你不能。您必须知道您的文件是用什么编码编写的。虽然 Unicde 编码文件可能以 BOM 开头,但我认为他们没有这样做的要求。

【讨论】:

  • 那么,是标记header,还是空格character
  • 那么,当作为标记使用时,转换成另一种格式时还是应该保留的字符吗?是否应该按wc -m(wc 字符数)计算?
  • 解释你的实际问题。
  • 我刚做了。空格作为标记头,即文件格式规范,还是算字符的字符吗?
  • 不,这是一个律师提出的问题,而不是这个问题的答案应该有助于解决的实际问题。
【解决方案2】:

我猜你是想问,为什么会有这些字符。这些字符可能是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!)

【讨论】:

  • 引用维基百科作为参考是一种不好的做法,您可能应该打破en.wikipedia.org/wiki/Wikipedia:Citing_Wikipedia。 Wikipedia 是开始研究和查找权威参考资料的好地方,但它永远不应该被用作参考资料,因为它具有无法验证的作者身份,并且在不知道作者的情况下,您无法知道其 cmets 的质量或准确性。指向官方 Unicode 站点的 wiki 文章中包含更好的参考:unicode.org/faq/utf_bom.html
  • 什么是 UTF-8 中的“字节顺序”?为什么要 UTF-8 中的字节顺序标记?
  • 来自w3.org/International/questions/qa-byte-order-mark :在 UTF-8 编码中,BOM 的存在不是必需的,因为与 UTF-16 编码不同,字符中没有替代的字节序列。但是,BOM 仍可能出现在 UTF-8 编码文本中,或者作为编码转换的副产品,或者因为它是由编辑器添加以将内容标记为 UTF-8。在这种情况下,BOM 通常称为 UTF-8 签名。
【解决方案3】:

当您将文件保存为 UTF-16 时,每个值是两个字节。不同的计算机使用不同的字节顺序。有些将最高有效字节放在首位,有些将最低有效字节放在首位。 Unicode 保留了一个特殊的代码点 (U+FEFF),称为字节顺序标记 (BOM)。当程序以 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,但文件开头除外 [Gillam, Richard, Unicode Demystified, Addison-Wesley, 2003 年,第108]。我的个人代码就是这样做的。如果在解码 UTF-8 时,我在文件开头看到 0xEF 0xBB 0xBF,我认为这是我确实拥有 UTF-8 的一个快乐信号。如果文件不是以这些字节开头,我只是正常进行解码。如果稍后在文件中解码时遇到 U+FEFF,我会发出 U+2060 并继续。这意味着 U+FEFF 仅用作 BOM 而不是其弃用的含义。

【讨论】:

  • "反对这样做的理由是,很多程序都需要 ASCII 或 UTF-8,并且不知道如何处理额外的三个字节。"我不跟。 EF BB BF 是 UTF-8,代表一个零宽度、不间断的空间——这基本上意味着“没有”,这就是它被选为 BOM 的原因。如果一个程序应该读取 UTF-8,它必须能够读取这个字符并知道如何处理它。
  • 比这强多了。不允许在 UTF 编码文件中省略 BOM。由于显而易见的原因,读取该文件的任何程序都无法猜测它包含 UTF 编码的文本。
  • @Hans:TTBOMK,BOM 始终是可选的,从不需要。
  • @sbi:嗯,你总是可以创建一个 o' 字节的包。但是,如果您将 UTF 编码文件交给没有 BOM 的第 3 方应用程序,请为“你在开玩笑吗!”做好准备。支持请求响应。
  • @sbi -- 不推荐使用 U+FEFF 作为零宽度、不间断的空格(例如参见 unicode.org/faq/utf_bom.html#bom6)。
【解决方案4】:

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

澄清一下,你应该意识到这个不是真的是一个字节顺序标记。字节顺序标记的基本思想根本不适用于 UTF-8。从理论上讲,永远不应该将 UTF-8 编码应用于 BOM - 但您可以忽略这一点,并将正常的 UTF-8 编码规则应用于构成 BOM 的值,如果您愿意的话。

【讨论】:

  • 说“永远不应该将 UTF-8 编码应用于 BOM”有点过分。将它用于字节排序是多余的,但它可以作为编码签名。见unicode.org/faq/utf_bom.html#bom5
  • @DanBreslau 从什么时候开始允许的?当 MS 说是?
  • @curiousguy 我为此引用了我的来源:unicode.org/faq/utf_bom.html#bom5 -- unicode.org 是管理 Unicode 标准的标准机构,因此定义了如何使用(或不使用)BOM。
  • @DanBreslau 只是因为 MS 坚持认为它是合法的。这是不合法的。
  • @curiousguy:我不是来抨击或捍卫微软的。哪个标准机构宣布“不合法”?
【解决方案5】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 2017-09-04
    • 2014-07-13
    • 1970-01-01
    相关资源
    最近更新 更多