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

myW*_*SON 6 c++ byte-order-mark utf-8

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

Ian*_*and 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
Run Code Online (Sandbox Code Playgroud)

但其他什么呢?如果您获得的字节数不是这五种模式中的一种,那么您无法确定您的文件是否为UTF-8.

实际上,任何只包含0x00到0x7f的ASCII字符的文本文档都是有效的UTF-8文档,也是纯ASCII文档.

有一些启发式方法可以尝试根据所看到的特定字符推断文档是否编码为ISO-8859-1,或UTF-8,或CP1252,但一般情况下,前两个,三个或者文件的四个字节不足以说明你所看到的是否肯定是UTF-8.


Joh*_*ohn 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
}
Run Code Online (Sandbox Code Playgroud)

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

BOM的维基

unicode.org.faq


小智 5

if (buffer[0] == '\xEF' && buffer[1] == '\xBB' && buffer[2] == '\xBF') {
    // UTF-8
}
Run Code Online (Sandbox Code Playgroud)

最好使用buffer[0] == '\xEF'而不是buffer[0] == 0xEF为了避免有符号/无符号字符问题,请参阅如何以十六进制表示负字符值?