Faced with the problem of reading the structure. When reading into a structure from a file, I get an incorrect value for the size of the file itself, which is indicated in the header. First of all, I checked it without structures, that is, I simply moved the pointer and read 4 bytes of information:

//пример seekp(2); imgf.read((char*)&buf, sizeof(int)); 

What gave me the correct file size. But it is much more convenient to implement all this through structures that I don’t have to do right. What is my mistake?

img.h file:

 #ifndef IMG_H #define IMG_H class img { public: img(char *); ~img(); // Заголовок файла typedef struct tagBITMAPFILEHEADER { unsigned short bfType; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned int bfOffBits; } BITMAPFILEHEADER; void read_bitmap_f(BITMAPFILEHEADER &); }; #endif // IMG_H 

img.cpp file:

 #include "img.h" #include <fstream> std::fstream imgf; img::img(char * name_of_img_) { imgf.open(name_of_img_); } void img::read_bitmap_f(BITMAPFILEHEADER &buf) { imgf.read((char*)&buf, sizeof(buf)); } img::~img() { imgf.close(); } 

main.cpp file:

 #include <iostream> #include "img.h" int main() { img * imgf = new img("lena512.bmp"); img::BITMAPFILEHEADER buf; imgf->read_bitmap_f(buf); std::cout << buf.bfSize << std::endl; // Выдает 4, хотя на самом деле изображение весит около 243КБ. return 0; } 
  • 2
    The compiler aligns the fields of the structure to optimize memory access. Therefore, bfSize you most likely will not be from the second byte, but from the fourth. - Vladimir Gamalyan
  • The pragma pack will most likely have to be used, the reason is described above. - Vladimir Martyanov
  • @ Vladimir Martianov Hmm, didn’t even think about it. I'll try to read about the pragma pack. - D Thr.
  • You also have an img class object created in main, but not deleted. - Vladimir Gamalyan
  • 2
    Possible duplicate question: reading structure from file in C - файла

2 answers 2

Instead of customizing the packaging structure, which, moreover, differs from compiler to compiler, it is better to consistently read the values ​​and enter them into the fields of this structure. Since we are dealing with C ++, for consistency, you can (and preferably) overload operator operator>> :

 std::istream& operator>> (std::istream& in, BITMAPFILEHEADER& value) { in >> value.bfType; in >> value.bfSize; in >> value.bfReserved1; in >> value.bfReserved2; in >> value.bfOffBits; return in; } 

Then the img.cpp file will look like this:

 // ... void img::read_bitmap_f(BITMAPFILEHEADER& buf) { imgf >> buf; } // ... 

UPD: In the comments @VladimirGamalian correctly noted that the author of the question opened the file in text mode. In order for the above code to work correctly, the file must be operated in binary mode.

  • Strange, the answer began to give a different one, namely, many orders of magnitude higher, but still incorrect. - D Thr.
  • one
    Overloaded so that stupid, but it works correctly. pastebin.com/AYXiYU5X - D Thr.
  • The answer does not take into account that std :: istream will extract values ​​from the textual representation. Those. This option will not work correctly. In pastebin.com/AYXiYU5X is already a working version, but keep in mind that on machines with Big Endian architecture will not work correctly. - Vladimir Gamalyan
  • @VladimirGamalian, thanks, added comments to your answer. - ߊߚߤߘ

Perhaps you have incorrectly aligned structure fields in memory. You can read about this, for example, in the article “ Dot the C / C ++ Structures ”.

You can fix, for example, like this:

 #pragma pack(push, 1) typedef struct tagBITMAPFILEHEADER { unsigned short bfType; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned int bfOffBits; } BITMAPFILEHEADER; #pragma pack(pop) 
  • 2
    For gcc, instead of the pragma pack, the use of ____attribute____ ((____packed____)) will be more native (two underscores, here it’s impossible to write correctly in the comments) - Vladimir Gamalyan