【问题标题】:Is this BOM in UTF-8 incorrect?这个 UTF-8 格式的 BOM 不正确吗?
【发布时间】:2021-02-01 06:32:51
【问题描述】:

我想用UTF-8验证BOM,下面写了c++代码。

但是,结果是0XFFFFFFEF, 0XFFFFFFBB, 0XFFFFFFBF

这与我的预期不同0XEF、0XBB、0XBF

为什么结果变成了上面?

顺便说一下,使用的UTF-8文件是Notepad++制作的。

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
        char file[]="/*UTF-8 file*/"; 
        
        char a[3]{};

        ifstream ifs(file, ios_base::binary);
        
        ifs.read(a, static_cast<streamsize>(sizeof(a)));
        
        cout << showbase << uppercase;
        
        for(int i:a){
                cout << hex << i << endl;
        }
}

环境

GCC 9.2.0

编译选项:-std=c++2a

【问题讨论】:

  • for(int i:a){char 数组上?嗯... 签名扩展.

标签: c++ gcc utf-8


【解决方案1】:

BOM 本身没问题。您只是错误地打印出字节。

您看到的结果是由于 sign extending 带符号的 8 位 char 值转换为带符号的 32 位整数。 charsigned 还是 unsigned 是编译器定义的,除非您在代码中明确声明。在您的情况下,您正在使用(隐式)签名的char。带符号的char 值 > 127 将其高位设置为 1,当将带符号的 8 位值扩展为带符号的 32 位值时,它将用 1 填充新位。

要正确输出字节,您需要将值进行零扩展,而不是符号扩展。为此使用unsigned 类型,例如:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    char file[] = "/*UTF-8 file*/";
    unsigned char a[3];

    ifstream ifs(file, ios_base::binary);
    ifs.read(reinterpret_cast<char*>(a), sizeof(a));

    cout << showbase << uppercase;

    for(unsigned int i : a){
        cout << hex << setw(2) << setfill(‘0’) << i << endl;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-28
    • 2018-09-01
    • 2012-02-12
    • 2011-07-21
    • 2012-05-19
    • 1970-01-01
    • 2016-05-04
    • 2021-03-09
    相关资源
    最近更新 更多