Отправка целого числа в fstream с прямым порядком байтов

Я пишу функцию для создания и сохранения файла WAV, но я не знаю, как отправлять числа в поток:

ofstream file;
file.open("sound.wav");
file << "RIFF";
file << (int) 32;
file << "WAVE";

Я пытаюсь реализовать эту файловую структуру WAVE: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/

и проблема в том, что вывод такой:

RIFF32WAVE

person Michal    schedule 07.02.2013    source источник


Ответы (3)


Оператор потоковой передачи << выполняет форматированный вывод — он преобразует значения в текст. Это не то, что вам нужно для записи в двоичный формат файла.

Вместо этого вы хотите использовать функции неформатированного вывода: put для отдельных байтов и write для нескольких байтов:

file.write("RIFF", 4);

// The length field is little-endian, so write the lowest byte first
file.put(length);
file.put(length >> 8);
file.put(length >> 16);
file.put(length >> 24);

file.write("WAVE", 4);

ОБНОВЛЕНИЕ: как отмечено в комментариях, вы также должны открыть файл в двоичном режиме и добавить в него классическую локаль «C», чтобы ничего не возиться с байтами, которые вы пишете:

file.open("sound.wav", std::ios_base::out | std::ios_base::binary);
file.imbue(std::locale::classic());
person Mike Seymour    schedule 07.02.2013
comment
Вы забыли упомянуть, что файл должен быть открыт в бинарном режиме и пропитан классической локалью. (В противном случае: приятно видеть, что кто-то предлагает чистое и правильное решение, а не просто хак, который работает только с некоторыми конкретными реализациями.) - person James Kanze; 07.02.2013
comment
@JamesKanze: Влияет ли что-либо из этого на неформатированный вывод? (Как программист Linux, пишущий код, который не нуждается в локализации, я никогда не удосужился подробно изучить эти вещи). - person Mike Seymour; 07.02.2013
comment
Да. В Unix нет реальной разницы между двоичным и текстовым, но почти во всех других системах она есть. И локали, отличные от классической локали, могут (и иногда делают) перекодировать ввод и вывод. (ИМХО, это также должно быть отключено в двоичном режиме. Но это не так; это полностью находится под контролем встроенной локали.) Я не знаю, навскидку, действительно ли какая-либо из доступных локалей выполняет перекодирование в Unix, но возможность существует. (FWIW: в codecvt есть функция always_noconv; если она возвращает true, все в порядке.) - person James Kanze; 07.02.2013
comment
Еще одна деталь: как различение двоичного/текстового, так и преобразование кода происходит в std::filebuf. Где они не знают, поступают ли символы из форматированного или неформатированного вывода. - person James Kanze; 07.02.2013
comment
@JamesKanze: Спасибо за объяснение, я добавил эти пункты в ответ. - person Mike Seymour; 07.02.2013

Вы должны открыть файл в режиме двоичного вывода, а затем распечатать в него.

См. этот вопрос, чтобы узнать, как это сделать.

person Ivaylo Strandjev    schedule 07.02.2013

Потоковые операторы предназначены для форматированного ввода-вывода (текст), а не бинарного. Вместо этого взгляните на метод записи. Что касается проблемы с прямым и прямым порядком байтов, вы можете просто использовать функцию htonl(), предоставляемую вашей ОС.

person Roger C    schedule 07.02.2013