使用 C++ 读回时将结构写入文件但值错误
Write struct to file but wrong value when read back with C++
我写了一些代码来读取 .wav 文件并做一些算法然后写入一个新的 .wav
file.I 在编写结构之前使用一个结构来代表 wav header到文件,里面的值都是正确的,但是当我回读的时候,里面的一些值改变了,我不知道为什么,这是我的结构:
struct WavHeader{
public:
char RIFF[4]={'R','I','F','F'};
int32_t size0;
char WAVE[4]={'W','A','V','E'};
char FMT[4]={'f','m','t',' '};
int32_t size1;
int16_t fmttag;
int16_t channel;
int32_t samplespersec;
int32_t bytepersec;
int16_t blockalign;
int32_t bitsEvrSample;
char DATA[4]={'d','a','t','a'};
int32_t size2;
WavHeader(){
size0=0;
size1=0;
fmttag=0;
channel=1;
samplespersec=0;
bytepersec=0;
blockalign=0;
bitsEvrSample=0;
size2=0;
}
};
这是我写入 wav 的函数(pz 忽略 WavData):
void MTools::write2Wav(const char* fname,WavData* data,WavHeader* wavhead){
FILE* fid=fopen(fname,"ab+");
fwrite(wavhead,1,sizeof(WavHeader),fid);
fclose(fid);
}
最后是我读取函数wav
header :
void MTools::loadWavFile(const char* fname,WavData* ret,WavHeader* head){
FILE* fp=fopen(fname,"rb");
size_t result;
if(fp){
char id[5];
format_length,sample_rate,avg_bytes_sec,data_size,bits_per_sample;
result=fread(id,sizeof(char),4,fp);
id[4]='[=12=]';
if(!strcmp(id,"RIFF")){
result=fread(&(head->size0),sizeof(int16_t),2,fp);
result=fread(id,sizeof(char),4,fp);
id[4]='[=12=]';
if(!strcmp(id,"WAVE")){
result=fread(id,sizeof(char),4,fp);
result=fread(&(head->size1),sizeof(int16_t),2,fp);
result=fread(&(head->fmttag),sizeof(int16_t),1,fp);
result=fread(&(head->channel),sizeof(int16_t),1,fp);
result=fread(&(head->samplespersec),sizeof(int16_t),2,fp);
result=fread(&(head->bytepersec),sizeof(int16_t),2,fp);
result=fread(&(head->blockalign),sizeof(int16_t),1,fp);
result=fread(&(head->bitsEvrSample),sizeof(int16_t),2,fp);
result=fread(id,sizeof(char),4,fp);
result=fread(&(head->size2),sizeof(int16_t),2,fp);
ret->size=head->size2/sizeof(int16_t);
ret->data=(int16_t*)malloc(head->size2);
result=fread(ret->data,sizeof(int16_t),ret->size,fp);
}
else{
cout<<"Error: RIFF File but not a wave file\n";
}
}
else{
cout<<"ERROR: not a RIFF file\n";
}
}
fclose(fp);
}
写之前(用gdb):
写入和回读后:
您将 header 定义为多种类型的混合,例如 int16
和 int32
。但是您只读过 int16
个值。例如看 samplespersec
。我想如果你调整类型,这可能是解决办法。
您需要像您的 loadWavFile 一样显式地重写您的 write2wav,因为您永远不知道结构中的数据是如何打包的(内存对齐问题),正如您所期望的那样(取决于编译器的编译器选项)。
我写了一些代码来读取 .wav 文件并做一些算法然后写入一个新的 .wav
file.I 在编写结构之前使用一个结构来代表 wav header到文件,里面的值都是正确的,但是当我回读的时候,里面的一些值改变了,我不知道为什么,这是我的结构:
struct WavHeader{
public:
char RIFF[4]={'R','I','F','F'};
int32_t size0;
char WAVE[4]={'W','A','V','E'};
char FMT[4]={'f','m','t',' '};
int32_t size1;
int16_t fmttag;
int16_t channel;
int32_t samplespersec;
int32_t bytepersec;
int16_t blockalign;
int32_t bitsEvrSample;
char DATA[4]={'d','a','t','a'};
int32_t size2;
WavHeader(){
size0=0;
size1=0;
fmttag=0;
channel=1;
samplespersec=0;
bytepersec=0;
blockalign=0;
bitsEvrSample=0;
size2=0;
}
};
这是我写入 wav 的函数(pz 忽略 WavData):
void MTools::write2Wav(const char* fname,WavData* data,WavHeader* wavhead){
FILE* fid=fopen(fname,"ab+");
fwrite(wavhead,1,sizeof(WavHeader),fid);
fclose(fid);
}
最后是我读取函数wav
header :
void MTools::loadWavFile(const char* fname,WavData* ret,WavHeader* head){
FILE* fp=fopen(fname,"rb");
size_t result;
if(fp){
char id[5];
format_length,sample_rate,avg_bytes_sec,data_size,bits_per_sample;
result=fread(id,sizeof(char),4,fp);
id[4]='[=12=]';
if(!strcmp(id,"RIFF")){
result=fread(&(head->size0),sizeof(int16_t),2,fp);
result=fread(id,sizeof(char),4,fp);
id[4]='[=12=]';
if(!strcmp(id,"WAVE")){
result=fread(id,sizeof(char),4,fp);
result=fread(&(head->size1),sizeof(int16_t),2,fp);
result=fread(&(head->fmttag),sizeof(int16_t),1,fp);
result=fread(&(head->channel),sizeof(int16_t),1,fp);
result=fread(&(head->samplespersec),sizeof(int16_t),2,fp);
result=fread(&(head->bytepersec),sizeof(int16_t),2,fp);
result=fread(&(head->blockalign),sizeof(int16_t),1,fp);
result=fread(&(head->bitsEvrSample),sizeof(int16_t),2,fp);
result=fread(id,sizeof(char),4,fp);
result=fread(&(head->size2),sizeof(int16_t),2,fp);
ret->size=head->size2/sizeof(int16_t);
ret->data=(int16_t*)malloc(head->size2);
result=fread(ret->data,sizeof(int16_t),ret->size,fp);
}
else{
cout<<"Error: RIFF File but not a wave file\n";
}
}
else{
cout<<"ERROR: not a RIFF file\n";
}
}
fclose(fp);
}
写之前(用gdb):
写入和回读后:
您将 header 定义为多种类型的混合,例如 int16
和 int32
。但是您只读过 int16
个值。例如看 samplespersec
。我想如果你调整类型,这可能是解决办法。
您需要像您的 loadWavFile 一样显式地重写您的 write2wav,因为您永远不知道结构中的数据是如何打包的(内存对齐问题),正如您所期望的那样(取决于编译器的编译器选项)。