C++17读取文本文件到std::string遇异常:开头乱码、c_str()输出截断
问题分析与解决
核心问题原因
- 开头的空格+方块符号:这是文件的字节顺序标记(BOM),常见于Windows系统下保存的UTF-16或带BOM的UTF-8文件。比如UTF-16LE的BOM是
0xFF 0xFE,用默认单字节方式读取时会被解析成两个奇怪字符;带BOM的UTF-8则是0xEF 0xBB 0xBF,同样会显示为不可见特殊字符。 - c_str()仅打印第一个字符:若文件是UTF-16编码,每个字符占两个字节,其中包含
'\0'(空字符)。C风格字符串以'\0'作为结束标记,输出到第一个'\0'就停止;而std::string支持存储'\0',直接输出text能显示完整内容。
解决方案
方案1:移除UTF-8 BOM并读取
如果文件是带BOM的UTF-8格式,可在读取时检测并跳过BOM:
#include <iostream> #include <sstream> #include <string> #include <fstream> const char* GetTextFile(const std::string& file_path, std::string& return_str) { std::ifstream file(file_path, std::ios::binary); if (!file.is_open()) { std::cout << "Error loading file: " << file_path << '\n'; return nullptr; } // 检测并跳过UTF-8 BOM unsigned char bom[3]; file.read(reinterpret_cast<char*>(bom), 3); if (!(bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)) { // 不是UTF-8 BOM,将文件指针移回开头 file.seekg(0); } std::stringstream buffer; buffer << file.rdbuf(); return_str = buffer.str(); return return_str.c_str(); } const std::string file_path = "dir\\file_name.ext"; int main() { std::string text; const char* c_style = GetTextFile(file_path, text); std::cout << text << '\n'; std::cout << c_style << '\n'; }
方案2:处理UTF-16编码文件
如果文件是UTF-16编码,需要先转成UTF-8格式的std::string:
#include <iostream> #include <string> #include <fstream> #include <locale> #include <codecvt> const char* GetTextFile(const std::string& file_path, std::string& return_str) { // 以UTF-16LE模式读取(Windows常见UTF-16格式),自动跳过BOM std::wifstream file(file_path); file.imbue(std::locale(file.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>)); if (!file.is_open()) { std::cout << "Error loading file: " << file_path << '\n'; return nullptr; } std::wstringstream buffer; buffer << file.rdbuf(); std::wstring wide_str = buffer.str(); // 转换为UTF-8编码的std::string std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; return_str = converter.to_bytes(wide_str); return return_str.c_str(); } const std::string file_path = "dir\\file_name.ext"; int main() { std::string text; const char* c_style = GetTextFile(file_path, text); std::cout << text << '\n'; std::cout << c_style << '\n'; }
方案3:重新保存文件(最简单)
用文本编辑器(如Notepad++)打开文件,选择编码 -> UTF-8无BOM或ANSI格式重新保存,再读取即可避免BOM问题。
额外注意
返回return_str.c_str()存在风险:若后续return_str被修改或销毁,返回的指针会变成野指针。建议直接返回std::string,在调用处再使用.c_str()。
内容的提问来源于stack exchange,提问作者Mohamed Othman
相关产品推荐
相关产品推荐

