【问题标题】:Read Access Violation when reading from file从文件读取时读取访问冲突
【发布时间】:2019-06-19 01:34:31
【问题描述】:

我正在尝试从已写入 Person 对象的 Person.txt 文件中读取。我收到此错误:抛出异常:读取访问冲突。 _Pnext 是 0x87E504。

我试过调试,它执行的功能很好。只有在函数完成后才会弹出错误。

这是我从文件中读取的代码:

void readFromFile()
{
    ifstream inFile("Person.txt", ios::in);

    Person p2;

    inFile.read(reinterpret_cast<char*>(&p2), sizeof(Person));

    cout << "First Name: " << p2.getFirst() << endl
        << "Last Name: " << p2.getlast() << endl
        << "Gender: " << p2.getgender() << endl
        << "Age: " << p2.getAge() << endl;



}

人物类:

Class Person {
public:
    Person()
    {
        firstName = "N/A";
        lastName = "N/A";
        gender = "N/A";
        age = 0;
    }

    Person(std::string first, std::string last, std::string gender, int age)
    {
        firstName = first;
        lastName = last;
        this->gender = gender;
        this->age = age;
    }

    ~Person()
    {
        std::cout << "Person Destructor" << std::endl;
    }

    void setFirst(std::string first)
    {
        firstName = first;
    }

    std::string getFirst() const
    {
        return firstName;
    }

    void setLast(std::string last)
    {
        lastName = last;
    }

    std::string getlast() const
    {
        return lastName;
    }

    void setGender(std::string gender)
    {
        this->gender = gender;
    }

    std::string getgender() const
    {
        return gender;
    }

    void setAge(int age)
    {
        this-> age = age;
    }

    int getAge() const
    {
        return age;
    }

private:
    std::string firstName;
    std::string lastName;
    std::string gender;
    int age;
};

【问题讨论】:

  • Person 的声明实际上是什么样的?我怀疑它包含指向动态分配数据的指针,例如std::string 数据成员内部。如果是这样,那么您将无法按原样写入/读取 Person 对象,您将需要单独序列化成员。
  • 我编辑它以显示 Person 类!
  • 任何时候你reinterpret_cast你都知道你的代码是错误的。在这种情况下,完全错误。
  • @AdamWinters 这很奇怪,因为我正在按照我的教科书做,而这正是他们所做的。 -- 所以多年来一直萦绕在我脑海中的谜团最终可能是解决了。你不是唯一一个以这种方式编写代码的人,我一直想知道是谁或什么在教这种方法。有数千个问题被标记为 C++ 与相同的问题,这种错误的技术不可能只是被粗心的语言学习者随机挑选出来的。
  • @RemyLebeau 这是真的吗?您是否保证genderage 之间的填充不会随编译标志、编译器版本或其他内容而改变?您是否保证 age 的字节表示不会随 CPU 版本、操作系统版本或其他内容而改变?它可能有效,但也可能无效,在书中教人们以这种方式编码是鲁莽的。

标签: c++ file class


【解决方案1】:

您的Person 类具有std::string 成员,其中包含指向存储在内存中其他位置的动态分配数据的指针。因此,您将无法按照您尝试的方式使用ofstream::write()ifstream::read() 写入/读取Person 对象。您只会写入/读取指针值,而不是指向的实际字符数据。您必须单独序列化数据成员。例如,在本例中,您可以简单地将每个字符串写入文本文件中自己的行,例如:

void writeToFile()
{
    ofstream outFile("Person.txt");

    Person p2("Joe", "Smoe", "M", 25);

    //outFile.write(reinterpret_cast<char*>(&p2), sizeof(Person));
    outFile << p2.getFirst() << "\n"
        << p2.getlast() << "\n"
        << p2.getgender() << "\n"
        << p2.getAge() << "\n";
}

void readFromFile()
{
    ifstream inFile("Person.txt");

    Person p2;
    string s;
    int i;

    //inFile.read(reinterpret_cast<char*>(&p2), sizeof(Person));
    getline(inFile, s);
    p2.setFirst(s);
    getline(inFile, s);
    p2.setLast(s);
    getline(inFile, s);
    p2.setGender(s);
    inFile >> i;
    inFile.ignore(numeric_limits<streamsize>::max(), '\n');
    p2.setAge(i);

    cout << "First Name: " << p2.getFirst() << endl
        << "Last Name: " << p2.getlast() << endl
        << "Gender: " << p2.getgender() << endl
        << "Age: " << p2.getAge() << endl;
}

我建议更进一步,将写入/读取逻辑移至Person 类本身:

Class Person {
public:
    Person()
    {
        firstName = "N/A";
        lastName = "N/A";
        gender = "N/A";
        age = 0;
    }

    Person(std::string first, std::string last, std::string gender, int age)
    {
        firstName = first;
        lastName = last;
        this->gender = gender;
        this->age = age;
    }

    ~Person()
    {
        std::cout << "Person Destructor" << std::endl;
    }

    void setFirst(std::string first)
    {
        firstName = first;
    }

    std::string getFirst() const
    {
        return firstName;
    }

    void setLast(std::string last)
    {
        lastName = last;
    }

    std::string getlast() const
    {
        return lastName;
    }

    void setGender(std::string gender)
    {
        this->gender = gender;
    }

    std::string getgender() const
    {
        return gender;
    }

    void setAge(int age)
    {
        this-> age = age;
    }

    int getAge() const
    {
        return age;
    }

    ostream& write(ostream &out) const
    {
        out << firstName << "\n"
            << lastName << "\n"
            << gender << "\n"
            << age << "\n";
        return out;
    }

    istream& read(istream &in)
    {
        getline(in, firstName);
        getline(in, lastName);
        getline(in, gender);
        in >> age;
        in.ignore(numeric_limits<streamsize>::max(), '\n');
        return in;
    }

private:
    std::string firstName;
    std::string lastName;
    std::string gender;
    int age;
};

ostream& operator<<(ostream &out, const Person &p)
{
    return p.write(out);
}

istream& operator>>(istream &in, Person &p)
{
    return p.read(in);
}

那么你可以这样做:

void writeToFile()
{
    ofstream outFile("Person.txt");

    Person p2("Joe", "Smoe", "M", 25);

    outFile << p2;
}

void readFromFile()
{
    ifstream inFile("Person.txt");

    Person p2;

    inFile >> p2;

    cout << "First Name: " << p2.getFirst() << endl
        << "Last Name: " << p2.getlast() << endl
        << "Gender: " << p2.getgender() << endl
        << "Age: " << p2.getAge() << endl;
}

【讨论】:

    猜你喜欢
    • 2014-12-23
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 2020-03-20
    • 1970-01-01
    相关资源
    最近更新 更多