#c #binary #integer #fstream
#c #двоичный #целое число #fstream
Вопрос:
Я записываю четыре целых числа (a = 1, b = 2, c = 3, d = 4) в двоичный файл на C с fstream
помощью, но когда я пытаюсь прочитать их обратно, они не совпадают.
Прежде всего, записанный двоичный файл имеет длину 4 байта. Разве это не должно быть 16 байт (4 целых x 4 байта / int)? Когда я читаю, я получаю странный результат 1234 2 3 4
, если я не инициализирую переменные нулем в функции чтения, или 1234 0 0 0
если я это делаю.
Кроме того, как изменяется результат при инициализации с нулевым значением? Я знаю, что отсутствие инициализации может привести к неприятным результатам, но как именно переменные в read() получают те значения, которые соответствуют значениям в write()?
#include <fstream>
#include <iostream>
void write()
{
std::ofstream output( "test.bin", std::fstream::binary | std::fstream::out);
int a=1, b=2, c=3, d=4;
output << a << b << c << d;
output.close();
}
void read()
{
std::ifstream input( "test.bin", std::fstream::binary | std::fstream::in);
int a, b, c, d;
// int a=0, b=0, c=0, d=0;
input >> a >> b >> c >> d;
input.close();
std::cout << a << " " << b << " " << c << " " << d << " " << std::endl;
}
int main()
{
write();
read(); // Shows 1234 2 3 4 or 1234 0 0 0
}
Комментарии:
1.
operator<<(..., int)
является FormattedOutputФункцией . Это форматирование целых чисел в виде строк без разделения между ними. Объединенные строки цифр выглядят неотличимыми от одного целого числа (1234), когда вы читаете его обратно. Вы можете тривиально подтвердить это, просмотрев свой собственный файл. Используйтеhexdump
или аналогичный, чтобы быть в безопасности, если вы ожидаете, что это будет непечатаемый двоичный файл.2. Вы записываете «1234», а затем считываете 1234 в
a
. Значенияb
,c
,d
в основном случайны, поэтому нулевой инициализации изменяет их.3. У меня сложилось впечатление, что для двоичного чтения / записи вы хотите использовать stream
.read
/.write
functions .4. @Cedric поскольку c 11
0
присваивается в случае сбоя извлечения. В любом случае нет ничего «случайного»5. @largest_prime_is_463035818 Что заставляет тебя так говорить? В случае присваивания (даже в C 11 и более поздних версиях) я бы сказал, что переменная ничего не передается, поскольку поток завершился с ошибкой перед извлечением, что означает, что он сохраняет свое предыдущее значение. В этом примере это явно не
0
так, поскольку значения1
,2
,3
. Я предполагаю, что они просто случайно попадают в ту же память, что и раньше, т.Е. Случайным образом.
Ответ №1:
output << a << b << c << d;
использует operator<<
оператор вставки потока, который предназначен для форматированного вывода. Все четыре целых числа форматируются как строки и выводятся без разделителя между ними.
Вы можете тривиально увидеть это, фактически просмотрев свой собственный файл (используйте hexdump
или аналогичный, если вы ожидаете, что файл будет содержать непечатаемые двоичные значения). Он содержит строку 1234
, не так ли?
Вам нужен неформатированный вывод, то есть вы не хотите, чтобы поток форматировал ваши целые числа в виде строк. Это делается путем вызова write
вместо (и read
вместо operator>>
).
Вывод:
output.write(reinterpret_cast<char *>(amp;a), sizeof(a));
output.write(reinterpret_cast<char *>(amp;b), sizeof(b));
// etc.
Ввод:
input.read(reinterpret_cast<char *>(amp;a), sizeof(a));
Возможно, вы ожидали std::fstream::binary
, что openmode предотвратит форматирование ваших целых чисел в виде строк при вставке потока, но это неверно: двоичный режим управляет только поведением новой строки. Операторы <<
and >>
всегда предназначены для форматированного ввода-вывода.