当我尝试用 C++ 解析二进制文件时,为什么会出现垃圾?

Why do I get garbage when I try to parse the binary file in C++?

我正在尝试用 C++ 解析 .wav 文件。
.wav 文件头中的 44 个字节是文件的一些元信息,我正在尝试解析这些信息。
我在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: RIFFL&
ChunkSize: 468556
Format: WAVEfmt 
FmtID: fmt 
FmtChunkSize: 16
FmtAudioFormat: 1
FmtChannelNumber: 1
FmtSampleRate: 44100
FmtByteRate: 88200
FmtBlockAlign: 2
FmtBitPerSample: 16
DataChunkID: data(&

问题是由四个字节的字符数组组成的三个字段。

ChunkID: RIFFL&Format: WAVEfmtDataChunkID: data(&
根据Python的解析,三个字段的内容应该是RIFFWAVEdata。 这是我的 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* ) &w, sizeof(WaveChunk));
    cout << WaveChunkToString(&w);
    return 0;
}

就是这样,为什么这三个字段解析的和预期的不一样,而其他由数字组成的字段没问题?

在这一行和其他行打印char something[4];:

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

std::stringstream 将读取到空字符 '[=14=]' 但数组不包含该字符,因此它将读取超出分配的缓冲区。

您必须指定要打印的大小才能在不添加额外字节的情况下正确打印数组。 可以这样做:

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