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

标签 c++ file file-io struct binary

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

struct Student
{
    char name[25];
    int quiz1;
    int quiz2;
    int quiz3;
};

它是 37 个字节(25 个字节来自 char 数组,每个整数 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

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

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));
}

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

*不包括文件打开和结构声明等类似部分

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));
}

输出:

Bart Simpson             16640179201818317312
ph Wiggum                288358417665884161394631027
impson                   129184563217692391371917853806
ince                     175193530917020655191851872800

唯一没有搞砸的是名字,之后是下山..我已经尝试了一切,但我不知道哪里出了问题。我什至翻遍了我所拥有的书籍,但我找不到任何东西。那里的东西看起来像我拥有的​​,而且它们可以工作,但出于某种奇怪的原因,我的却没有。我在第 25 个字节处执行了 file.get(ch)(ch 是一个字符),它返回了 K,它是 75 的 ASCII 码。这是第一个测试分数,所以,一切都在它应该在的地方。只是没有正确读取我的结构。

任何帮助将不胜感激,我只是坚持使用这个。

编辑:在收到你们这么多意想不到的好消息后,我决定采纳你们的建议,坚持一次读一个成员。我通过使用函数让事情变得更干净、更小。 再次感谢您提供如此快速和富有启发性的意见。非常感谢。

如果您对大多数人不推荐的解决方法感兴趣,请向下滚动到 user1654209 的第三个答案。该变通方法完美无缺,但请阅读所有评论以了解其不受青睐的原因。

最佳答案

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

由于填充很可能位于字符串和整数之间,因此即使是第一条记录也无法正确读取。

在这种情况下,我建议不要尝试将数据读取为二进制 blob,而是坚持读取单个字段。它要强大得多,尤其是当您甚至想改变您的结构时。

关于c++ - 将二进制文件读入结构 (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15542617/

相关文章:

c++ - 为什么每个人都对标准 C 类型进行 typedef?

c++ - Qt 退出应用程序并显示另一个窗口

php - 使用mpdf在php中插入pdf格式的图像

android - 制作私有(private)文件夹

c++ - std::ifstream 是否比 FILE 慢得多?

JavaScript/Firefox 写入本地驱动器上的文本文件示例

c++ - is_move_constructible 和 msvc2013

c++ - 确定可变参数 C++11 模板化 lambda 函数的返回类型

PHP上传文件Mysql失败

java - apache httpcomponent 和 sftp 协议(protocol) - 可以使用该协议(protocol)吗?