You need to enable JavaScript to run this app. C++无法读取.dat文件中存储的vector类型数据问题求助
优惠活动
大模型
产品
解决方案
定价
更多

C++无法读取.dat文件中存储的vector类型数据问题求助

C++读取.dat文件中vector数据失败问题解决

核心问题原因

你当前代码的错误根源是直接对包含非POD类型(vector、string都属于非POD类型)的类对象做二进制读写操作:

  • vector和string内部仅存储指向堆内存的指针,实际的字符串、元素数据都存在堆空间
  • 你用outfile.write(reinterpret_cast<char*>(this),sizeof(*this))写入的只是对象本身的内存数据,其中包含的是当前进程的堆指针地址,不是实际的元素内容
  • 首次运行写入后立刻读取能正常显示,是因为当前进程里指针指向的堆内存还没释放,地址是有效的;下次重启进程后,之前写入的指针地址在新的进程空间里完全无效,自然读不到数据

修复方案

需要手动实现类的序列化/反序列化逻辑,不能直接读写整个对象:

  1. 写入时:先写入vector的元素个数,再逐个写入每个string的长度、再写入字符串实际内容
  2. 读取时:先读vector的元素个数,再逐个读每个string的长度、再读对应长度的字符串内容存入vector

修改后的可运行代码

#include<iostream>
#include<vector>
#include<string>
#include<fstream>
using namespace std;

class Symptom {
public:
    vector<string> symptomList;
    string symptom;
    const string fileName = "disease.dat";
    char ch;

    // 序列化Symptom到文件
    void serialize(ofstream& outfile) {
        // 先写symptomList的大小
        size_t listSize = symptomList.size();
        outfile.write(reinterpret_cast<char*>(&listSize), sizeof(listSize));
        // 逐个写入每个symptom
        for (const string& s : symptomList) {
            size_t strLen = s.size();
            outfile.write(reinterpret_cast<char*>(&strLen), sizeof(strLen));
            outfile.write(s.c_str(), strLen);
        }
    }

    // 从文件反序列化Symptom
    void deserialize(ifstream& infile) {
        symptomList.clear();
        // 先读symptomList的大小
        size_t listSize;
        infile.read(reinterpret_cast<char*>(&listSize), sizeof(listSize));
        // 逐个读取每个symptom
        for (size_t i = 0; i < listSize; i++) {
            size_t strLen;
            infile.read(reinterpret_cast<char*>(&strLen), sizeof(strLen));
            string s(strLen, '\0');
            infile.read(&s[0], strLen);
            symptomList.push_back(s);
        }
    }

    // 调用该方法添加疾病对应的症状列表
    void addSymptom() {
        int i = 0;
        cout<<"输入疾病对应的症状:"<<endl;
        symptomList.clear();
        do {
            // 插入每个症状到symptomList
            cout<<++i<<". ";
            getline(cin, symptom);
            symptomList.push_back(symptom);

            cout<<"是否要输入下一个症状?(y/n)";
            cin>>ch;
            cin.get();// 配合循环内getline使用,清除换行符缓存
        } while(ch=='y'||ch=='Y');      
    }

    // 展示该疾病的所有症状
    void showSymptom() {
        cout << "症状列表:"<<endl;
        for (auto it = symptomList.begin(); it != symptomList.end(); ++it)
            cout << " - " << *it << endl;
    }
};

class Disease {
public:
    Symptom symptoms;
    const string fileName = "disease.dat";

    // 添加疾病信息到文件
    void addDisease() {
        char ch;
        ofstream outfile(fileName, ios::binary | ios::out);
        if(!outfile.is_open()) {
            cout<<"打开文件失败";
            return;
        }
        // 先预留位置存储疾病总个数,后续写入完成后回来更新
        size_t diseaseCount = 0;
        streampos countPos = outfile.tellp();
        outfile.write(reinterpret_cast<char*>(&diseaseCount), sizeof(diseaseCount));

        do {
            symptoms.addSymptom();
            symptoms.serialize(outfile);
            diseaseCount++;
            cout<<"\n是否要输入下一个疾病的信息?(y/n)";
            cin>>ch;
            cin.get();
        } while(ch=='y'||ch=='Y');
        // 回到文件开头更新疾病总数
        outfile.seekp(countPos);
        outfile.write(reinterpret_cast<char*>(&diseaseCount), sizeof(diseaseCount));
        outfile.close();
    }

    // 从文件读取疾病信息
    void getDisease() {  
        ifstream infile(fileName, ios::binary);
        if(!infile.is_open()) {
            cout<<"打开文件失败";
            return;
        }
        // 先读取疾病总数
        size_t diseaseCount;
        infile.read(reinterpret_cast<char*>(&diseaseCount), sizeof(diseaseCount));
        for (size_t i = 0; i < diseaseCount; i++) {
            symptoms.deserialize(infile);
            symptoms.showSymptom();
        }
        infile.close();
    }
};

int main() {
    Disease d;
    // d.addDisease(); // 新增疾病信息
    d.getDisease(); // 展示疾病信息
    return 0;
}

内容的提问来源于stack exchange,提问作者Nawaraj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 13:27:03