C ++如何检查文件字节顺序标记以获取它是否为UTF-8?

时间:2012-02-01 21:00:45

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

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

4 个答案:

答案 0 :(得分:10)

一般情况下,你不能。

字节顺序标记的存在非常强烈地表明您正在读取的文件是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。

答案 1 :(得分:5)

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

答案 2 :(得分:4)

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?

答案 3 :(得分: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.
}