c++ - binaryfiles - 如何正确读取和写入二进制文件 (C++ )?

103 5

在这个程序中,我读取,操作和写入位图二进制文件,我尝试使用c样式读取和写入这些文件,为了将内存块写入另一个文件,我使用new()和delete动态地将内存分配到堆上,不知怎么地,我看到输出文件被文件和信息头覆盖。


#include <cstdint>


#include <cstdio>



#pragma pack(push, 2)


struct BitmapFileHeader {



 uint16_t type;


 uint32_t size;


 uint16_t reserved_1;


 uint16_t reserved_2;


 uint32_t offset;



};


struct BitmapInfoHeader {



 uint32_t size;


 uint32_t width;


 uint32_t height;


 uint16_t planes;


 uint16_t bitcount;


 uint32_t compression;


 uint32_t imagesize;


 uint32_t x_pixels_per_meter;


 uint32_t y_pixels_per_meter;


 uint32_t color_used;


 uint32_t color_important;


};


#pragma pack(pop)



struct Pixel {


 uint8_t blue;


 uint8_t green;


 uint8_t red;


};



int main(int argc, char* argv[])


{


 if(argc != 3) {


 printf("Usage : %s input_file output_filen", argv[0]);


 return 1;


 }



 FILE *fin;


 FILE *fout;


 BitmapFileHeader bfh;


 BitmapInfoHeader bih;



 fin = fopen(argv[1],"rb");



 if (nullptr == fin) {


 perror(argv[1]);


 return -1;


 }



 if (sizeof(BitmapFileHeader) != fread(


 &bfh,


 1,


 sizeof(bfh),


 fin


 )) {


 printf("Unable to read bitmap file header. n");


 return -2;


 }



 if (sizeof(BitmapInfoHeader) != fread(


 &bih,


 1,


 sizeof(bih),


 fin


 )) {


 printf("Unable to read bitmap info header. n");


 return -3;


 }



 printf("Size of File Header = %lun", sizeof(BitmapFileHeader));



 int8_t first = (bfh.type >> 8) & 0xff;


 int8_t second = bfh.type & 0xff;



 if ( (first != 'M') && (second != 'B') ){


 printf("Input file is not a Bitmap file. n");


 return -4;


 }



 printf("File type = %c%cn", first, second);


 printf("File size = %un", bfh.size);


 printf("File offset = %un", bfh.offset);


 printf("File width = %un", bih.width);


 printf("Info size = %un", bih.size);



 uint32_t padding_bytes = 0;


 uint32_t row_bytes_final = bih.width * sizeof(Pixel);


 uint32_t row_bytes_initial = row_bytes_final;



 do{


 uint32_t rem = row_bytes_final % 4;



 if (rem != 0) {


 row_bytes_final += 1;


 }



 padding_bytes = row_bytes_final - row_bytes_initial;



 } while( (row_bytes_final % 4) != 0);



 fseek(fin, bfh.offset, SEEK_SET);



 Pixel *p = new Pixel[bih.height * bih.width];



 for (uint32_t i = 0; i < (bih.height); i++) {



 for (uint32_t j = 0; j < bih.width; j++) {


 fread(&p[i], 1, sizeof(p), fin);


 i++;


 //Something I don't understand is wrong here. 


 }



 fseek(fin, padding_bytes, SEEK_CUR);



 }



 fclose(fin);



 fout = fopen(argv[2],"wb");



 if(nullptr == fout) {


 perror(argv[2]);


 return -5;


 }



 if( sizeof(BitmapFileHeader) != fwrite(


 &bfh, 


 1, 


 sizeof(bfh), 


 fout


 )) {


 printf("Unable to write bitmap file header.n");


 return -6;


 }



 if( sizeof(BitmapInfoHeader) != fwrite(


 &bih, 


 1, 


 sizeof(bih), 


 fout


 )) {


 printf("Unable to write bitmap info header.n");


 return -7;


 }



 fseek(fout, bfh.offset, SEEK_SET);



 for (uint32_t i = 0; i < (bih.height) ; i++) {



 for (uint32_t j = 0; i < bih.width; j++) {


 fwrite(&p[i], 1, sizeof(p), fout);


 i++;


 //same problem


 }



 fseek(fout, padding_bytes, SEEK_CUR);



 }



 fclose(fout);


 delete p;



 //fseek(fin, bfh.offset, SEEK_SET);


 //Pixel p;


 //fread(&p, 1, sizeof(p), fin);


 //printf("R = %u, G = %u, B = %un", p.red, p.green, p.blue);


 return 0;



}



如果我将文件指针移到偏移量,如何覆盖输出文件的头部?

时间: 原作者:

75 2

我在你的代码中看到以下问题:

问题1

你正在使用错误的参数sizeof


fread(&p[i], 1, sizeof(p), fin);




fwrite(&p[i], 1, sizeof(p), fout);



它们需要是sizeof(p[i])sizeof(p[0])sizeof(Pixel) ,我更喜欢sizeof(p[0]),因为它不管p[0]的类型如何。

问题2

你有一个错误


for (uint32_t j = 0; i < bih.width; j++) {



它需要


for (uint32_t j = 0; j < bih.width; j++) {


// ^^^ Fix



问题3

你没有使用正确的索引存储到p中,并从p写入。


for (uint32_t i = 0; i < bih.height; i++) {


 for (uint32_t j = 0; j < bih.width; j++) {



 // Using p[i] is not correct. You need to use the right index.


 // sizeof(p[0]) is just as good as sizeof(p[index]) here.



 uint32_t index = i*bih.width + j;


 fread(&p[index], 1, sizeof(p[0]), fin);


 }


 fseek(fin, padding_bytes, SEEK_CUR);


}



写作循环需要修正。


for (uint32_t i = 0; i < bih.height; i++) {


 for (uint32_t j = 0; j < bih.width; j++) {


 uint32_t index = i*bih.width + j;


 fwrite(&p[index], 1, sizeof(p[0]), fout);


 }


 fseek(fout, padding_bytes, SEEK_CUR);


}



原作者:
115 5

我认为 fread(&p[i], 1, sizeof(p), fin);应该是 fread(&p[i], 1, sizeof(Pixel), fin);

指针的大小(基于体系结构)通常为4或8字节,像素类是3个字节(使用 #pragma pack(push ,1))。

可能使用 fread(&p[i], sizeof(Pixel), bih.width, fin);但是要注意,顺序和填充在不同的体系结构上可能有所不同。

原作者:
...