Почему я получаю мусор, когда пытаюсь разобрать двоичный файл на C ?

#c #wav

#c #wav

Вопрос:

Я пытаюсь разобрать WAV-файлы на C .
44 байта в заголовке файла .wav-файл — это некоторая метаинформация файла, которую я пытаюсь проанализировать.
Я проанализировал его на Python и получил следующее, что должно быть правильным

 Chunk_id  :  RIFF
Chunk_size  :  468556
Format  :  WAVE
fmt_id  :  fmt 
fmt_size  :  16
audio_format  :  1
channels_count  :  1
sample_rate  :  44100
byte_rate  :  88200
block_align  :  2
bits_per_sample  :  16
data_id  :  data
data_size  :  468520
 

Но когда я переключаюсь на C , я получаю следующее:

 ChunkID: RIFFLamp;
ChunkSize: 468556
Format: WAVEfmt 
FmtID: fmt 
FmtChunkSize: 16
FmtAudioFormat: 1
FmtChannelNumber: 1
FmtSampleRate: 44100
FmtByteRate: 88200
FmtBlockAlign: 2
FmtBitPerSample: 16
DataChunkID: data(amp;
 

Проблема заключается в трех полях, состоящих из массива символов из четырех байт.

ChunkID: RIFFLamp; , Format: WAVEfmt , DataChunkID: data(amp;
В соответствии с анализом Python содержимое трех полей должно быть RIFF , WAVE , data . И это мой код на C .

 #include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct WaveChunk
{
        char ChunkID[4];
        int ChunkSize;
        char Format[4];

        // fmt
        char FmtID[4];
        int FmtChunkSize;
        short FmtAudioFormat;
        short FmtChannelNumber;

        int FmtSampleRate;
        int FmtByteRate;
        short FmtBlockAlign;
        short FmtBitPerSample;
        // fmt

        // data
        char DataChunkID[4];
        int DataChunkSize;
        // data
};

string WaveChunkToString(WaveChunk* wavechunk){
    stringstream ss;
    ss << "ChunkID: " << wavechunk->ChunkID << "n";
    ss << "ChunkSize: " << wavechunk->ChunkSize << "n";
    ss << "Format: " << wavechunk->Format << "n";

    ss << "FmtID: " << wavechunk->FmtID << "n";
    ss << "FmtChunkSize: " << wavechunk->FmtChunkSize << "n";
    ss << "FmtAudioFormat: " << wavechunk->FmtAudioFormat << "n";
    ss << "FmtChannelNumber: " << wavechunk->FmtChannelNumber << "n";
    ss << "FmtSampleRate: " << wavechunk->FmtSampleRate << "n";
    ss << "FmtByteRate: " << wavechunk->FmtByteRate << "n";
    ss << "FmtBlockAlign: " << wavechunk->FmtBlockAlign << "n";
    ss << "FmtBitPerSample: " << wavechunk->FmtBitPerSample << "n";
    ss << "DataChunkID: " << wavechunk->DataChunkID << "n";
    ss << "DataChunkSize: " << wavechunk->DataChunkSize << endl;
    return ss.str();
}

using namespace std;
int main(){
    WaveChunk w;
    ifstream inf("target.wav", ios::binary|ios::in);
    inf.read((char* ) amp;w, sizeof(WaveChunk));
    cout << WaveChunkToString(amp;w);
    return 0;
}
 

Вот и все, почему эти три поля анализируются не так, как ожидалось, но другие поля, состоящие из чисел, в порядке?

Ответ №1:

В этой строке и других строках для печати char something[4]; :

     ss << "ChunkID: " << wavechunk->ChunkID << "n";
 

std::stringstream будет считываться до нулевого символа '' , но массив не содержит его, поэтому он будет считываться за пределы выделенного буфера.

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

     ss << "ChunkID: "; ss.write(wavechunk->ChunkID, 4); ss << "n";