最近有个需求,需要解析txt文件,发现如果是带BOM(也就是带签名)的UTF8文件,无法正常被识别,究其原因,发现如果带签名,则会错误解析签名部分,当做内容解析了,从而导致后续无法正常识别。
在网上找了一下,没有找到直接可用的代码,于是参照网上解析txt的代码,然后自己整理了一个函数,经过测试可用。
基本原理就是判断文件的前三个字节是不是BOM签名,代码如下:
//author:autumoon
//联系QQ:4589968
//日期:2022-01-17
bool IsBOMUtf8(const char* szFilePath)
{
std::ifstream t;
t.open(szFilePath); // open input file
if (!t.is_open())
{
return false;
}
t.seekg(0, std::ios::end); // go to the end
int length = t.tellg(); // report location (this is the length)
if (length < 3)
{
return false;
}
t.seekg(0, std::ios::beg); // go back to the beginning
char *buffer = new char[3](); // allocate memory for a buffer of appropriate dimension
t.read(buffer, 3); // read 3 bytes into the buffer
t.close(); // close file handle
bool bRet = buffer[0] == (char)0xEF && buffer[1] == (char)0xBB && buffer[2] == (char)0xBF;
delete[] buffer;
buffer = nullptr;
return bRet;
}
附带一个txt读取到std::string的代码,供参考:
//author:autumoon
//联系QQ:4589968
//日期:2022-01-17
bool TxtToStdString(const char* szTxtPath, std::string& sTxtStr, bool bIsUtf8)
{
bool bIsBOMUtf8 = IsBOMUtf8(szTxtPath);
std::ifstream t(szTxtPath);
if (!t.is_open())
{
return false;
}
if (bIsBOMUtf8)
{
char a;
t >> a;
t >> a;
t >> a;
//此时为BOMUtf8
bIsUtf8 = true;
}
std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
if (bIsUtf8)
{
std::wstring ws = rj_utf8_to_wstring(str);
sTxtStr = rj_ws2s(ws);
}
else
{
sTxtStr = str;
}
return true;
}
欢迎交流与讨论。