将文件读入结构(C++)

vin*_*ind 5 c++ binary struct file

我正在尝试从二进制文件中读取数据并将其放入结构中.前几个字节data.bin是:

03 56 04 FF FF FF ...
Run Code Online (Sandbox Code Playgroud)

我的实施是:

#include <iostream>
#include <fstream>

int main()
{
    struct header {
        unsigned char type;
        unsigned short size;
    } fileHeader;

    std::ifstream file ("data.bin", std::ios::binary);
    file.read ((char*) &fileHeader, sizeof header);

    std::cout << "type: " << (int)fileHeader.type;
    std::cout << ", size: " << fileHeader.size << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

我期待的输出是type: 3, size: 1110,但由于某种原因它是type: 3, size: 65284,所以基本上跳过文件中的第二个字节.这里发生了什么事?

Naw*_*waz 7

实际上,行为是实现定义的.在你的情况下实际发生的事情可能是,type在结构的成员之后有一个1字节的填充,然后在第二个成员之后size.在看到输出之后,我根据这个论点.

这是你的输入字节:

03 56 04 FF FF FF
Run Code Online (Sandbox Code Playgroud)

第一个字节03转到结构的第一个字节,即type,您将其3视为输出.然后下一个字节56转到第二个字节,这是填充因此被忽略,然后接下来的两个字节04 FF转到结构的下一个两个字节size(大小为2字节).在little-endian机器上,04 FF被解释为0xFF04哪个只是66284你得到的输出.

而且你基本上需要一个紧凑的结构来挤压填充物.使用#pragma包.但是与普通结构相比,这样的结构会很慢.更好的选择是手动填充结构:

char bytes[3];
std::ifstream file ("data.bin", std::ios::binary);
file.read (bytes, sizeof bytes); //read first 3 bytes

//then manually fill the header
fileHeader.type = bytes[0];
fileHeader.size = ((unsigned short) bytes[2] << 8) | bytes[1]; 
Run Code Online (Sandbox Code Playgroud)

写最后一行的另一种方法是:

fileHeader.size = *reinterpret_cast<unsigned short*>(bytes+1); 
Run Code Online (Sandbox Code Playgroud)

但这是实现定义的,因为它取决于机器的endian-ness.在little-endian机器上,它很可能会起作用.

友好的方法是这个(实现定义):

std::ifstream file ("data.bin", std::ios::binary);
file.read (&fileHeader.type, sizeof fileHeader.type);
file.read (reinterpret_cast<char*>(&fileHeader.size), sizeof fileHeader.size);
Run Code Online (Sandbox Code Playgroud)

但同样,最后一行取决于机器的字节序.