【发布时间】:2020-11-17 22:47:05
【问题描述】:
尝试编译此代码时:
std::fstream file("file.name", std::ios::out | std::ios::binary);
uint8_t buf[BUFSIZE];
//Fill the buffer, etc...
file.write(buf, BUFSIZE);
编译器会在调用write() 时警告我从unsigned char 到char 的哦不那么健康的转换。由于std::fstream 实际上只是std::basic_fstream<char> 的typedef,人们可能会认为使用std::basic_fstream<uint8_t> 可以让他们在没有警告的情况下编译上面的代码,因为write() 需要模板类型的指针。
这当然可行,但又出现了另一个问题。即使这段代码编译得很好:
std::basic_fstream<uint8_t> file("file.name", std::ios::out | std::ios::binary);
uint8_t buf[BUFSIZE];
//Fill the buffer, etc...
file.write(buf, BUFSIZE);
现在调用write() 时会失败,即使之前的版本正在运行(忽略编译器警告)。我花了一段时间来确定标准 C++ 库代码中异常是从哪里引发的,但我仍然不太明白这里的情况。看起来std::basic_fstream 使用了一些字符编码机制,并且由于为char 定义了一个但没有为unsigned char 定义一个,因此在尝试使用“错误”字符数据类型时文件流会静默失败......就是这样至少我看到了。
但这也是我不明白的。不需要任何字符编码。我什至不以文本模式打开文件,我想处理二进制数据。这就是为什么我使用uint8_t 类型的数组,而不是char,使用这种数据类型而不是普通的旧char 感觉更自然。但在我决定放弃 uint8_t 数据类型并接受使用 char 缓冲区,或开始使用定义为 char 的自定义 byte 数据类型数组之前,我想问两个问题:
- 究竟是什么机制阻止我使用无符号字符数据类型?它真的与字符编码有关,还是有其他用途?为什么文件流适用于有符号字符数据类型,但不适用于无符号数据类型?
- 假设我仍然想使用
std::basic_fstream<uint8_t>,不管它有多么(不)合理 - 有什么方法可以实现吗?
【问题讨论】:
-
流的内部结构根本不支持
unsigned char。让它正常使用char,您只需对write()执行类型转换,例如:std::ofstream file("file.name", std::ios::binary); ... file.write(reinterpret_cast<char*>(buf), BUFSIZE); -
我知道,但是太丑了。
-
别担心
reinterpret_cast,妈妈还是爱你的。 -
@PookyFan 丑不丑,不过这是你必须要做的事情
-
是的,要么使用
char数组。但这整个问题都来自于寻找替代解决方案,因为这两种解决方案都没有真正吸引我。但如果我要从两者中进行选择,我想我宁愿使用兼容的数组,也不愿将指针仅用于写入数据,特别是如果代码中有更多的write()调用。
标签: c++ std fstream codecvt char-traits