错误地读取或写入二进制文件

时间:2018-03-04 08:33:07

标签: c++

代码的输出显示了Student结构的所有变量的乱码值。当显示功能运行时。

我在二进制文件的每个添加和显示功能中都包含相关代码。

对于第二个函数,每次for循环运行时,seekg指针是否自动移动以读取下一条记录?

//Student struct
struct Student
{
    char name [30];
    float labTest;
    float assignments;
    float exam;
};

//Writing function   
afile.open(fileName,ios::out|ios::binary);

Student S;
strcpy(S.name,"test");
S.labTest = rand()%100+1;
S.assignments = rand()%100+1;
S.exam = rand()%100+1;

afile.write(reinterpret_cast<char*>(&S),sizeof(S));

afile.close();



//Reading function
afile.open(fileName,ios::in|ios::binary);

afile.seekg(0,ios::end);

int nobyte = afile.tellg();
int recno = nobyte / sizeof(Student);

Student S;

//Loop and read every record
for(int i = 0;i<recno;i++)
    {
        afile.read(reinterpret_cast<char*>(&S),sizeof(S));
        cout << "Name of Student: " << S.name << endl
        << "Lab mark: " << S.labTest << endl
        << "Assignment mark: " << S.assignments << endl
        << "Exam mark: " << S.exam << endl << endl;
    }

afile.close();

1 个答案:

答案 0 :(得分:3)

您的代码存在很多问题:

调用写入函数将永久覆盖最后写入的数据集。您必须添加:ios::append,以便在您之前编写的最后一个数据后面写入新数据。

使用afile.seekg(0,ios::end);移动以获得tellg文件大小后,您必须返回文件的开头才能阅读afile.seekg(0,ios::beg)

看起来您使用char数组来存储字符串。这不是c ++风格!你如何使用它很危险。如果使用strcpy,则可以复制长度超过为其保留的空间的字符串。所以你应该更喜欢std::string。但是你不能简单地编写一个以std::string为二进制的结构!要获得选中的副本,您可以使用strncpy,但这仍然不是c ++;)

  

对于第二个函数,每次for循环运行时,seekg指针是否会自动移动以读取下一条记录?

是的,文件位置移动,每次成功读写。

通过简单地转储内存内容来编写二进制数据的一般注释: 这不是一个好主意,因为如果使用相同的机器类型和相同的编译器选项,则只能读回该数据。这意味着:具有不同字节序的机器将读取完全损坏的数据。另外一个不同的整数类型(32位对64位)将破坏该代码!

因此,您应该花一些时间以便携方式序列化数据。有很多库可用于读/写复杂的数据类型,如std :: string或容器类型。

使用SO的提示: 请提供每个人都可以简单地剪切和粘贴和编译的代码。我不知道你的Student结构是什么。所以我采取了很多假设!你的struct真的使用char []吗?我们不知道!

#include <iostream>
#include <fstream>
#include <cstring>

const char* fileName="x.bin";

struct Student
{
    char name[100]; // not c++ style!
    int labTest;
    int assignments;
    int exam;
};

// Writing function   
void Write()
{
    std::ofstream afile;
    afile.open(fileName,std::ios::out|std::ios::binary|std::ios::app);

    Student S;
    strcpy(S.name,"test"); // should not be done this way! 
    S.labTest = rand()%100+1;
    S.assignments = rand()%100+1;
    S.exam = rand()%100+1;

    afile.write(reinterpret_cast<char*>(&S),sizeof(S));

    afile.close();
}

void Read()
{
    //Reading function
    std::ifstream afile;
    afile.open(fileName,std::ios::in|std::ios::binary);

    afile.seekg(0,std::ios::end);

    int nobyte = afile.tellg();
    int recno = nobyte / sizeof(Student);

    afile.seekg(0, std::ios::beg);

    Student S;

    //Loop and read every record
    for(int i = 0;i<recno;i++)
    {
        afile.read(reinterpret_cast<char*>(&S),sizeof(S));
        std::cout << "Name of Student: " << S.name << std::endl
            << "Lab mark: " << S.labTest << std::endl
            << "Assignment mark: " << S.assignments << std::endl
            << "Exam mark: " << S.exam << std::endl << std::endl;
    }

    afile.close();
}

int main()
{
    for ( int ii= 0; ii<10; ii++) Write();
    Read();
}