Почему я не могу читать двоичные данные fstream с помощью оператора >>?

Если я делаю что-то вроде следующего:

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

unsigned int data;

file >> data;

Мой поток всегда будет устанавливать failbit, а data останется неинициализированным. Однако, если я прочитал вместо char или unsigned char, поток прекрасен. perror() говорит мне, что "результат слишком велик".

Единственное, что я видел в Google, было предложение о том, что operator>> не следует использовать для двоичных данных (предпочитайте read()), но я считаю, что оператор будет более чистым и простым в использовании - и это не делает 't требуют лить все.

Может кто-нибудь объяснить эту проблему?

Ответ 1

оператор извлечения iostream ( → ) пытается интерпретировать числовые строки, разделенные пробелами, а не двоичные данные. Существует множество способов кодирования целого числа без знака в двоичной форме (например, 32-битное представление 2 дополнений в порядок байтов с байтовым порядком). Вот почему вы должны использовать read/write для работы с такими бинарными буферами.

Однако ничто не мешает вам реализовать свой собственный класс для сериализации двоичных данных в любой форме, какой вы хотите, используя операторы вставки и извлечения. Такой класс, скорее всего, будет использовать функцию чтения объекта ifstream внутри. Альтернативно, повысить библиотеку сериализации может уже содержать именно то, что вы хотите.

Ответ 2

Это должно быть сделано, как описано вами. Однако стандартные дизайнеры С++ не очень элегантны. На самом деле в дизайне С++ есть много недостатков, даже С++ 11 и С++ 14 имеют множество дефектов.

Идеальный дизайн С++ должен быть таким:

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. Возможно, это может быть достигнуто в С++ 22.