将二进制文件读入结构(C++)

B.K*_*.K. 8 c++ binary file-io struct file

所以我遇到了一个无法正确读取二进制文件到我的结构中的问题.结构是这样的:

struct Student
{
    char name[25];
    int quiz1;
    int quiz2;
    int quiz3;
};
Run Code Online (Sandbox Code Playgroud)

它是37个字节(来自char数组的25个字节,每个整数4个字节).我的.dat文件是185个字节.这是5名学生,有3个整数等级.因此每个学生占用37个字节(37*5 = 185).

它看起来像这样的纯文本格式:

Bart Simpson          75   65   70
Ralph Wiggum          35   60   44
Lisa Simpson          100  98   91
Martin Prince         99   98   99
Milhouse Van Houten   80   87   79
Run Code Online (Sandbox Code Playgroud)

我可以使用以下代码单独读取每个记录:

Student stud;

fstream file;
file.open("quizzes.dat", ios::in | ios::out | ios::binary);

if (file.fail())
{
    cout << "ERROR: Cannot open the file..." << endl;
    exit(0);
}

file.read(stud.name, sizeof(stud.name));
file.read(reinterpret_cast<char *>(&stud.quiz1), sizeof(stud.quiz1));
file.read(reinterpret_cast<char *>(&stud.quiz2), sizeof(stud.quiz2));
file.read(reinterpret_cast<char *>(&stud.quiz3), sizeof(stud.quiz3));

while(!file.eof())
{
    cout << left 
         << setw(25) << stud.name
         << setw(5)  << stud.quiz1
         << setw(5)  << stud.quiz2
         << setw(5)  << stud.quiz3
         << endl;

    // Reading the next record
    file.read(stud.name, sizeof(stud.name));
    file.read(reinterpret_cast<char *>(&stud.quiz1), sizeof(stud.quiz1));
    file.read(reinterpret_cast<char *>(&stud.quiz2), sizeof(stud.quiz2));
    file.read(reinterpret_cast<char *>(&stud.quiz3), sizeof(stud.quiz3));
}
Run Code Online (Sandbox Code Playgroud)

我得到一个漂亮的输出,但我希望能够一次读取一个完整的结构,而不是一次只读取每个结构的单个成员.这段代码是我认为完成任务所需要的,但是......它不起作用(我会在它之后显示输出):

*不包括类似的部分,只要打开文件和结构声明等.

file.read(reinterpret_cast<char *>(&stud), sizeof(stud));

while(!file.eof())
{
    cout << left 
         << setw(25) << stud.name
         << setw(5)  << stud.quiz1
         << setw(5)  << stud.quiz2
         << setw(5)  << stud.quiz3
         << endl;

    file.read(reinterpret_cast<char *>(&stud), sizeof(stud));
}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

Bart Simpson             16640179201818317312
ph Wiggum                288358417665884161394631027
impson                   129184563217692391371917853806
ince                     175193530917020655191851872800
Run Code Online (Sandbox Code Playgroud)

唯一没有搞乱的部分就是名字,之后就是下山了......我已经尝试了一切,我不知道出了什么问题.我甚至搜索过我的书,我找不到任何东西.那里的东西看起来像我拥有的​​东西而且它们起作用,但由于一些奇怪的原因,我的东西没有.我在第25个字节做了file.get(ch)(ch是一个字符),然后它返回K,这是第7个测试分数的ASCII.所以,一切都应该是它.它只是没有正确阅读我的结构.

任何帮助将不胜感激,我只是坚持这一个.

编辑: 在收到你们这么大的意外和令人敬畏的意见之后,我决定接受你的建议并坚持一次阅读一个成员.我通过使用功能使事情更清洁,更小. 再次感谢您提供如此快速和启发性的输入.非常感谢.

如果您对大多数人不推荐的解决方法感兴趣,请向用户1654209滚动到底部,到第3个答案.该解决方案完美无瑕,但阅读所有评论,看看为什么它不受青睐.

Jas*_*onD 9

您的结构几乎肯定已经填充以保持其内容的对齐.这意味着它不会是37个字节,并且不匹配会导致读数不同步.看看每个字符串丢失3个字符的方式,它似乎已被填充到40个字节.

由于填充可能在字符串和整数之间,因此即使第一条记录也没有正确读取.

在这种情况下,我建议不要尝试将数据作为二进制blob读取,并坚持阅读单个字段.它更强大,特别是如果你甚至想改变你的结构.

  • @JasonD我不了解您,但是我宁愿将定义放在一个地方:结构的定义,而不是逐字段阅读。为什么?因为(如果您担心)数据布局中的任何更改,唯一需要更新的地方就是结构的定义。但是,如果您逐场读取,则代码中读取该数据的每个位置都与其格式紧密相关,因此必须进行更新,这可能是维护方面的噩梦。 (2认同)