C++ 不正确地读取或写入二进制文件

C++ 不正确地读取或写入二进制文件,c++,C++,代码的输出显示Student结构的所有变量的乱码值。当显示功能运行时 我已经在二进制文件的每个add和display函数中包含了相关代码 对于第二个函数,seekg指针是否会在每次For循环运行时自动移动以读取下一条记录 //Student struct struct Student { char name [30]; float labTest; float assignments; float exam; }; //Writing function a

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

我已经在二进制文件的每个add和display函数中包含了相关代码

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

//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();
//学生结构
体类型
{
字符名[30];
浮标试验;
浮动分配;
浮动考试;
};
//书写功能
打开(文件名,ios::out | ios::binary);
学生证;
strcpy(S.名称,“测试”);
S.labTest=rand()%100+1;
S.assignments=rand()%100+1;
S.exam=rand()%100+1;
文件写入(重新解释铸件,尺寸);
afile.close();
//阅读功能
打开(文件名,ios::in | ios::binary);
afile.seekg(0,ios::end);
int nobyte=afile.tellg();
int recno=nobyte/sizeof(学生);
学生证;
//循环并读取每条记录

对于(int i=0;i,您的代码有很多问题:

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

使用
afile.seekg(0,ios::end);
移动后,要使用
telg
显示文件大小,必须先返回文件开头,然后再使用
afile.seekg(0,ios::beg)

看起来你使用一个字符数组来存储一个字符串。这不是C++风格。使用它是很危险的。如果你使用StrcPy,你可以复制一个比你预留的空间长的字符串。所以你应该更喜欢<代码> STD::String 。但是你不能简单地写一个结构,它把代码< >代码:ST::String < /C> >作为BINA。RY!要获得检查副本,可以使用<代码> StncPy < /C> >,但仍然不是C++;

对于第二个函数,每次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();
是的,每次成功读写所移动的文件位置

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

因此,您应该投入一些时间来以可移植的方式序列化数据。有很多库可以用来读/写复杂的数据类型,比如std::string或container类型

使用SO的提示: 请提供代码,每个人都可以简单地剪切、粘贴和编译。我不知道你的
学生
结构是什么。所以我做了很多假设!你的结构真的在使用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();
}
#包括
#包括
#包括
常量字符*fileName=“x.bin”;
体类型
{
char name(100);//不是C++风格!
int-labTest;
整数赋值;
智力测验;
};
//书写功能
无效写入()
{
std::流文件;
打开(文件名,std::ios::out | std::ios::binary | std::ios::app);
学生证;
strcpy(S.name,“test”);//不应该这样做!
S.labTest=rand()%100+1;
S.assignments=rand()%100+1;
S.exam=rand()%100+1;
文件写入(重新解释铸件,尺寸);
afile.close();
}
无效读取()
{
//阅读功能
std::ifstream-afile;
打开(文件名,std::ios::in | std::ios::binary);
a文件。请参见kg(0,std::ios::end);
int nobyte=afile.tellg();
int recno=nobyte/sizeof(学生);
afile.seekg(0,std::ios::beg);
学生证;
//循环并读取每条记录

对于(inti=0;iEDIT.显然,我的回答有点太晚了。Klaus编写了一个更好、更全面的回答,涉及到关于C风格
char[]
std::string
和平台的结尾的其他问题

您应该附加到为每个记录打开的文件中。在您的代码中,您根本没有附加。请以我们可以复制、粘贴和测试的方式编写代码。作为一个工作示例,您应该编写一些可以编译和运行的代码,如下所示:

#包括
#包括
#包括
#包括
#包括
#包括
//学生结构
结构学生{
字符名[30];
浮标试验;
浮动分配;
浮动考试;
};
//序列化程序
void serialize_student(常量student&s,常量std::string和filename){
//附加到文件,不要覆盖它
流输出文件的std::of(文件名,std::ios::binary | std::ios::app);
如果(输出文件)
outfile.write(重新解释cast&s),sizeof(学生);
}
//反序列化器
std::vector反序列化_学生(const std::string和filename){
std::ifstream infle(文件名,std::ios::binary);
性病:病媒学生;
学生证;
while(infle.read(reinterpret_cast&s)、sizeof(Student)))
学生们。推回(std::移动);
返回std::移动(学生);
}
int main(int argc,char*argv[]){
//生成记录
std::向量mystudents;
std::generate_n(std::back_inserter(mystudents),10,[](){
学生证;
标准::strcpy(s.name,“test”);
s、 labTest=rand()%100+1;
s、 赋值=rand()%100+1;
s、 考试=兰德()%100+1;
返回s;
});
//打印并写入记录
用于(const auto和student:mystudents){

你能调用
afile.close()吗
,在那之后,你不能用
文件做任何事情。很抱歉,它们是两个独立的函数,所以我事先打开了它们。它们只是不包含在代码中。你需要显示一个什么是
学生
?你能把它插入你的示例吗!@TulaMalek:得到答案后,你应该决定它是否适合你的需要。如果所以,你应该接受答案,如果不接受,就发表评论,这样可以改进答案