问题 为什么我不能用operator >>读取fstream的二进制数据?


如果我执行以下操作:

ifstream file;
file.open("somefile", ios::binary);

unsigned int data;

file >> data;

我的流将始终设置 failbit 和 data 将保持未初始化状态。但是,如果我读了一个 char 要么 unsigned char 相反,流是好的。 perror() 告诉我“结果太大”。

我在谷歌上看到的唯一一件事是建议说 operator>> 不应该用于二进制数据(更喜欢 read()),但我发现操作员更清洁,更容易使用 - 并且它不需要铸造所有东西。

有人可以解释这个问题吗?


7456
2017-11-11 06:16


起源



答案:


iostream提取运算符(>>) 试图解释由空格分隔的数字字符串,而不是二进制数据。有许多不同的方法来编码二进制形式的无符号整数(例如32位 2的补码表示 在 little-endian字节顺序)。这就是你必须使用的原因 / 用于操作这种二进制缓冲区的函数。

但是,没有什么能阻止您使用插入和提取操作符实现您自己的类,以便以任何形式序列化二进制数据。这样的类可能会在内部使用ifstream对象的read函数。或者, 提升序列化库 可能已经完全掌握了你想要的东西。


11
2017-11-11 06:21





它应该按照你的描述完成。但是,C ++标准设计师并不是很优雅。事实上,C ++的设计存在很多缺陷,即使C ++ 11和C ++ 14也有很多缺陷。

理想的C ++设计应该是:

1.对于文本文件:

ifstream fin_txt("input.txt");
int i;
float j;
double k;
fin_txt >> i >> j >> k;

这将读入3个字符串并解析为整数,float和double,并分别将它们存储到i,j和k中。

2.对于二进制文件:

ifstream fin_txt("input.bin", ios::binary);
int i;
float j;
double k;
fin_txt >> i >> j >> k;

这将读取4/8字节(取决于int是32位还是64位),4字节和8字节二进制数据,并分别将它们存储到i,j和k中。

不幸, 目前的设计 是报告案例2的错误。也许这可以在C ++ 22中实现。


0
2018-04-13 13:51



你有这样的理由在你的答案中这样:“取决于int是32位还是64位”。目前,代码使用 <iostreams> 是便携式的,你的建议不是。 - Caleth


答案:


iostream提取运算符(>>) 试图解释由空格分隔的数字字符串,而不是二进制数据。有许多不同的方法来编码二进制形式的无符号整数(例如32位 2的补码表示 在 little-endian字节顺序)。这就是你必须使用的原因 / 用于操作这种二进制缓冲区的函数。

但是,没有什么能阻止您使用插入和提取操作符实现您自己的类,以便以任何形式序列化二进制数据。这样的类可能会在内部使用ifstream对象的read函数。或者, 提升序列化库 可能已经完全掌握了你想要的东西。


11
2017-11-11 06:21





它应该按照你的描述完成。但是,C ++标准设计师并不是很优雅。事实上,C ++的设计存在很多缺陷,即使C ++ 11和C ++ 14也有很多缺陷。

理想的C ++设计应该是:

1.对于文本文件:

ifstream fin_txt("input.txt");
int i;
float j;
double k;
fin_txt >> i >> j >> k;

这将读入3个字符串并解析为整数,float和double,并分别将它们存储到i,j和k中。

2.对于二进制文件:

ifstream fin_txt("input.bin", ios::binary);
int i;
float j;
double k;
fin_txt >> i >> j >> k;

这将读取4/8字节(取决于int是32位还是64位),4字节和8字节二进制数据,并分别将它们存储到i,j和k中。

不幸, 目前的设计 是报告案例2的错误。也许这可以在C ++ 22中实现。


0
2018-04-13 13:51



你有这样的理由在你的答案中这样:“取决于int是32位还是64位”。目前,代码使用 <iostreams> 是便携式的,你的建议不是。 - Caleth