Linux下std::basic_fstream<unsigned char>调用read()失败如何解决?
问题根因说明
你遇到的问题是GNU libstdc++(Linux默认C++标准库)的设计差异导致的:默认locale仅为char类型提供了codecvt facet的默认实现,没有对应unsigned char的特化版本,因此basic_fstream<unsigned char>初始化时无法获取到可用的编码转换facet,调用读写接口时就会触发bad_cast异常。Windows的MSVC标准库对unsigned char特化的文件流做了额外兼容,所以同一段代码可以正常运行。
修复方案
方案1:改用char类型的文件流(最推荐)
二进制读写场景下char和unsigned char的内存存储完全一致,直接改用默认的fstream(即basic_fstream<char>),读入后再转成unsigned char指针使用即可,改造成本最低,跨平台兼容性最好。
修改后代码示例:
#include <fstream> #include <string> using namespace std; int main() { fstream fs; basic_string<unsigned char> buf(1000, '\0'); fs.open("/tmp/file.txt", ios::in | ios::binary); fs.read(reinterpret_cast<char*>(&buf[0]), 1000); // 后续正常使用buf即可 return 0; }
方案2:自定义unsigned char的codecvt特化
如果必须保留basic_fstream<unsigned char>的写法,可以手动实现对应特化的codecvt facet,二进制场景下直接继承char类型的实现即可:
#include <locale> #include <fstream> #include <string> using namespace std; // 手动特化unsigned char对应的codecvt template<> struct std::codecvt<unsigned char, char, std::mbstate_t> : std::codecvt<char, char, std::mbstate_t> {}; int main() { basic_fstream<unsigned char> fs; basic_string<unsigned char> buf(1000, '\0'); fs.open( "/tmp/file.txt", ios::in | ios::binary); fs.read( &buf[0], 1000); return 0; }
方案3:为流手动注入可用的locale
也可以在打开流前,为basic_fstream<unsigned char>手动注入包含可用codecvt的locale:
#include <fstream> #include <string> #include <locale> using namespace std; int main() { basic_fstream<unsigned char> fs; // 注入带char类型codecvt的locale fs.imbue(std::locale(std::locale(), new std::codecvt<char, char, std::mbstate_t>)); basic_string<unsigned char> buf(1000, '\0'); fs.open( "/tmp/file.txt", ios::in | ios::binary); fs.read( &buf[0], 1000); return 0; }
内容的提问来源于stack exchange,提问作者Al Berger
相关产品推荐
相关产品推荐

