【问题标题】:Reading and writing C++ objects into Random access files将 C++ 对象读取和写入随机访问文件
【发布时间】:2014-01-20 11:15:00
【问题描述】:

我是 C++ 初学者,我想做的是读写我在程序中创建的 Staff 对象。

下面是我的Write方法:

void Staff::writeStaffFile(){
const int vectorSize = staffList.size();
ofstream staffDetailsFile("staffDetails.txt", ios::out | ios::binary);
if (!staffDetailsFile){
    cerr << "\nFile open error - Error writing staff details" << endl;
    return;
    }

for (int i=0; i<vectorSize; i++){
    staffDetailsFile.write(reinterpret_cast< const char* >(&staffList[i]), sizeof(Staff));
    }
staffDetailsFile.close();
}

Staff 对象保存在向量中,在这里我尝试将向量中可用的所有这些人员对象保存到文件中。它工作并将数据写入文件。

我出错的地方是读取文件。这是我的阅读方法:

void Staff::readStaffFile(){
ifstream staffDetailsFile("staffDetails.txt", ios::in | ios::binary);
if (!staffDetailsFile)
    cerr << "\nFile open error - Staff details not found" << endl;
else {
    Staff *temp = (Staff *)malloc(sizeof(Staff));
    while(!staffDetailsFile.eof()){
        staffDetailsFile.read(reinterpret_cast<char *>(temp),sizeof(Staff));
        if (temp != NULL)
            Staff::insertAccount(temp);
        }
    }
}

当我运行这部分时,我在 Visual Studio 中收到以下错误。

StaffPersonnelSystem.exe 中 0x53950E9A (msvcr110d.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00F5BF28。

我似乎无法理解我哪里出错了,如果有人可以帮助我处理这段代码,我将非常感激。

PS:这是我的员工类定义:

#include <iostream>
#include <string>
#include <malloc>
#include <vector>
#include "Person.h"

#ifndef STAFF_H
#define STAFF_H

class Staff : public Person {

public:
    Staff(int const, string,string,int,string,string,char,Designation,Department,Date,string,string,Date,bool); //staff constructor

    //set methods
    void setStaffIDNumber(int const);
    void setUsername(string);
    void setPassword(string);
    void setAccessLevel(int);


    //edit, modify other staff accounts
    static void addStaff(int);
    static int generateStaffID();
    static void deleteStaff(int, Staff*);
    static void changePassword(Staff*);
    static bool modifyStaff(int, Staff*);
    static void insertAccount(Staff*);
    static void printStaffDetails(Staff*);
    static void writeStaffFile();
    static void readStaffFile();
    static bool isValidAccount(Staff*,string, string);
    static Staff* chooseStaffAccount();
    static void searchStaff();
    static void refreshVector();

    //get methods
    Staff getStaffAccount(string);
    int getAccessLevel();
    string getUserName();
    int getStaffID();
    string getPassword();

    //search staff accounts
    static Staff* searchStaffAccount(string); //search staff accounts by userName
    static Staff* searchByID(int); //search staff accounts by ID
    static void searchByDept(Department); //Get staff registered to perticular department
    static void searchByDesignation(Designation); //Get staff registered to perticular designation
    static void sortVector();
    static bool sortByID(Staff &lhs, Staff &rhs);
    static bool isVectorEmpty();

private:
    int staffIDNumber;
    string userName;
    string passWord;
    int accessLevel;

    };

#endif

【问题讨论】:

  • 向我们展示 Staff 类定义。
  • 序列化和反序列化的常用方法是重载插入/提取运算符,让您的类接受并返回 ostream& / istream& ,然后在这些方法中调用各个数据成员的插入/提取运算符。仅当您的所有数据成员都是基元而不是指针或引用时,memcpy 才会起作用。在您的情况下,您有两个字符串数据成员(userName 和 passWord),它们将它们的 char 数组存储在您的对象之外,并作为指向缓冲区的指针保存。 (暂时忽略 SSO 的任何影响)。
  • 写一个minimal example,在调试模式下编译并使用调试器。作为一名程序员,你只会花 10% 的时间编写代码和 90% 的时间调试它。

标签: c++ vector file-handling


【解决方案1】:

你犯了几个错误。首先是认为你 可以对写入文件的按位图像执行任何操作。 全部 程序外的数据必须以某种方式格式化。如果你 想要二进制格式,你需要函数来格式化和解析 一个int 和一个string。 (除非有充分的理由 否则,您可能应该使用现有格式:XDR 可能是最简单的。)

如果您的数据都是基本数据类型(intchar[] 等), 写入和读取按位图像可能看起来 工作。直到您更改编译器选项或版本,或尝试 使用另一个系统。即使是基本类型也需要格式化。 (和 当然,任何带有指针的东西都需要格式化; std::string 几乎肯定有指针 实施。)

最后:您使用staffDetailsFile.read 的结果 没有测试读取是否成功。那是 未定义的行为。你的循环应该是while ( staffDetailsFile.read( ... ) )。 (但这只会让你 未格式化的缓冲区;您仍然需要提取数据。 而且很可能你甚至不知道要读取多少字节, 因为std::string 的格式可能有一个变量 长度。)

【讨论】:

    【解决方案2】:

    您不能将 Staff 类型的对象写入文件,将其读回并期望它会起作用。只有当你的班级是 POD(普通旧数据)时,这样的事情才有可能。您的 Staff 类不是 POD - 它包含字符串对象。 顺便说一句,您的测试 if (temp != NULL) 是错误的 - 如果在读取调用之前 temp 不是 NULL,那么它之后就不会是 NULL。

    【讨论】:

    • 即使是 POD,如果您以后使用不同的选项或不同版本的编译器进行编译,您也不能期望将其读回。
    猜你喜欢
    • 2018-04-05
    • 2011-11-15
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多