UTF-8编码中的BOM问题

来源:互联网 发布:淘宝一元买东西在哪里 编辑:程序博客网 时间:2024/04/30 04:06

背景:

在将一个文件从excel另存为txt的时候,以UTF-8的方式进行保存为a.txt。在C++中通过getline的方式逐行读取发现第一行的数据出现读取错误的情况。

分析:

将该文件另存为UTF-8的无BOM格式,再读取的时候,则可以正常读取。

在UCS 编码(即 Unicode编码)中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输 字符”ZERO WIDTH NO-BREAK SPACE”。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little- Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE”的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。

UTF- 8编码的文件中,BOM占三个字节。如果用记事本把一个文本文件另存为UTF-8编码方式的话,用UE打开这个文件,切换到十六进制编辑状态就可以看到开 头的FFFE了,如下图所示。这是个标识UTF-8编码文件的好办法,软件通过BOM来识别这个文件是否是UTF-8编码,很多软件还要求读入的文件必须带BOM。可 是,还是有很多软件不能识别BOM。
这里写图片描述
从上图可以看出EF BB BF开头的字符,该行的字符出现显示编码异常。而采用UTF-8无BOM存储方式如下,可以看出,第一行的数据正常显示。
这里写图片描述

带有BOM的正常读取方案

最简单的方法就是直接另存为无BOM的UTF-8格式。如果是带有BOM的UTF-8,则先要去除其BOM头。
判断是否存在BOM:

bool HasBom(const char* decKrc, uint32_t decKrcLen){    if (decKrcLen >= 3         && (unsigned char)decKrc[0] == 0xef         && (unsigned char)decKrc[1] == 0xbb         && (unsigned char)decKrc[2] == 0xbf)    {        return true;    }    return false;}

正式代码:

    ifstream Inputread("a.txt");    string str;    while(getline(Inputread,str))    {        bool hasBom1 = HasBom(str.c_str(), str.size());        if (hasBom1)            str= str.substr(3);        //对该行内容的处理操作    }

即可实现该行数据的正常读取。在去掉BOM之后,保留的文本如下:
这里写图片描述

0 0
原创粉丝点击