【问题标题】:C++ How to inspect file Byte Order Mark in order to get if it is UTF-8?C ++如何检查文件字节顺序标记以确定它是否为UTF-8?
【发布时间】:2012-02-24 13:46:47
【问题描述】:

我想知道如何检查文件字节顺序标记以确定它是否是 C++ 中的 UTF-8?

【问题讨论】:

  • 有什么问题?您需要做的就是将其与 0xEF、0xBB、0xBF 进行比较。我认为您需要详细说明您的问题。
  • 使用任何语言的方式都一样。你得到前三个字节。如果它们看起来像 Unicode 字节顺序标记的 UTF-8 字节,那么它就是 UTF-8。如果他们不这样做,那就不是。您是在找人为您编写源代码吗?
  • Nicol——“如果他们不这样做,那就不是”——不是真的。如果它们看起来不像 BOM,那么它很容易仍然是 UTF-8。不需要使用 UTF-8 编码的字节顺序标记。
  • @Nicol 建议您删除或编辑该评论,因为它是错误的。看起来像 Unicode BOM 的字节序列只会告诉您它可能是 Unicode 数据。它可能意味着“”。

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


【解决方案1】:

这是我的 C++ 版本:

#include <fstream>

/* Reads a leading BOM from file stream if it exists.
 * Returns true, iff the BOM has been there. */
bool ReadBOM(std::ifstream & is)
{
  /* Read the first byte. */
  char const c0 = is.get();
  if (c0 != '\xEF') {
    is.putback(c0);
    return false;
  }

  /* Read the second byte. */
  char const c1 = is.get();
  if (c1 != '\xBB') {
    is.putback(c1);
    is.putback(c0);
    return false;
  }

  /* Peek the third byte. */
  char const c2 = is.peek();
  if (c2 != '\xBF') {
    is.putback(c1);
    is.putback(c0);
    return false;
  }

  return true; // This file contains a BOM for UTF-8.
}

【讨论】:

    【解决方案2】:
    if (buffer[0] == '\xEF' && buffer[1] == '\xBB' && buffer[2] == '\xBF') {
        // UTF-8
    }
    

    最好使用buffer[0] == '\xEF' 而不是buffer[0] == 0xEF 以避免有符号/无符号字符问题,请参阅How do I represent negative char values in hexadecimal?

    【讨论】:

    • 我必须结合使用 ifstream.read(..)(不是 get())和 char 文字来匹配 BOM 字节。干杯!
    【解决方案3】:

    一般来说,你不能。

    字节顺序标记的存在非常强烈地表明您正在阅读的文件是 Unicode。如果您期待一个文本文件,并且您收到的前四个字节是:

    0x00, 0x00, 0xfe, 0xff -- The file is almost certainly UTF-32BE
    0xff, 0xfe, 0x00, 0x00 -- The file is almost certainly UTF-32LE
    0xfe, 0xff,  XX,   XX     -- The file is almost certainly UTF-16BE
    0xff, 0xfe,  XX,   XX (but not 00, 00) -- The file is almost certainly UTF-16LE
    0xef, 0xbb, 0xbf,  XX   -- The file is almost certainly UTF-8 With a BOM
    

    但是其他的呢?如果您获得的字节不是这五种模式之一,那么您不能确定您的文件是还是不是 UTF-8。

    事实上,任何仅包含从 0x00 到 0x7f 的 ASCII 字符的文本文档都是有效的 UTF-8 文档,也是纯 ASCII 文档。

    有一些启发式方法可以尝试根据看到的特定字符来推断文档是用 ISO-8859-1、UTF-8 还是 CP1252 编码的,但一般来说,第一个一个文件的两个、三个或四个字节都不足以说明您正在查看的内容是否绝对是 UTF-8。

    【讨论】:

    • “(but not 00, 00)”是否适用于 UTF-16BE 和 UTF-16LE,还是仅适用于后者?
    • fe ff 00 00 将是 UTF16-BE,而不是 UTF32。在 UTF-32 中,它将表示 U+FFFE,它是一个非字符,不应出现在任何 Unicode 文档中。在 UTF-16BE 中,它是一个 BOM,后跟一个空字符
    【解决方案4】:

    0xEF,0xBB,0xBF

    排序不依赖于字节序。

    如何使用 C++ 读取文件取决于您。就我个人而言,我仍然使用 C 风格的 File 方法,因为它们是由我正在编码的库提供的,我可以确保指定为二进制模式并避免意外的翻译。

    改编自cs.vt.edu

    #include <fstream>
    ...
    char buffer[100];
    ifstream myFile ("data.bin", ios::in | ios::binary);
    myFile.read (buffer, 3);
    if (!myFile) {
        // An error occurred!
        // myFile.gcount() returns the number of bytes read.
        // calling myFile.clear() will reset the stream state
        // so it is usable again.
    }
    ...
    if (!myFile.read (buffer, 100)) {
        // Same effect as above
    }
    if (buffer[0] == 0XEF && buffer[1] == 0XBB && buffer[2] == 0XBF) {
        //Congrats, UTF-8
    }
    

    或者,如果没有指定其他 BOM(例如 UTF-16 或 UTF-32),许多格式默认使用 UTF-8。

    wiki for BOM

    unicode.org.faq

    【讨论】:

      猜你喜欢
      • 2011-07-13
      • 1970-01-01
      • 2016-04-25
      • 2012-04-17
      • 2019-10-08
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      相关资源
      最近更新 更多