文件读写std::string的问题

lambdaios / 2024-01-16 / 原文


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdexcept>
#include<algorithm>
#include<fstream>
#include<string>

class make {
public:
    //make(const char* name, int age) {
    //    this->age = age;
    //    std::strcpy(this->name, name);
    //}

    make(std::string name, int age) {
        this->name = name;
        this->age = age;
    }
    make() {}

    //char name[64];
    std::string name;
    //std::string类中有一个成员指针char* 该指针指向储存字符串的空间
    //当我们把string类的数据存储到文件中,再读出来时,不能保证指针有效
    
    int age;
};

//写文件
void test01() {
    make m1("123", 123);
    make m2("456", 456);

    std::ofstream ofs;
    ofs.open("test.txt",std::ios::out | std::ios::trunc | std::ios::binary);
    if (!ofs.is_open()) {
        std::cout << "open fail\n";
    }

    //写
    //ofs.write((const char*)&m1, sizeof(make));
    //ofs.write((const char*)&m2, sizeof(make));
    ofs.write((const char*)&m1, sizeof make);
    ofs.write((const char*)&m2, sizeof make);
    ofs.close();
}

//read file

void test02() {
    std::ifstream ifs;
    ifs.open("test.txt", std::ios::in | std::ios::binary);
    if (!ifs.is_open()) {
        std::cout << "打开失败\n";
    }

    //read file
    make m1, m2;
    
    ifs.read((char*)&m1, sizeof(make));
    ifs.read((char*)&m2, sizeof(make));

    std::cout << "name:" << m1.name << " age:" << m1.age << '\n';
    std::cout << "name:" << m2.name << " age:" << m2.age << '\n';

    ifs.close();
}

auto main()->int32_t{
   

    test01();
    test02();
    return static_cast<int>(0);
}



正确的做法是分段读


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdexcept>
#include<algorithm>
#include<fstream>
#include<string>

class make {
public:
    make(std::string name, int age) {
        this->name = name;
        this->age = age;
    }
    make() {}

    std::string name;
    int age;
};

// 写文件
void test01() {
    make m1("123", 123);
    make m2("456", 456);

    std::ofstream ofs;
    ofs.open("test.txt", std::ios::out | std::ios::trunc | std::ios::binary);
    if (!ofs.is_open()) {
        std::cout << "open fail\n";
    }

    // 写入年龄
    ofs.write((const char*)&m1.age, sizeof(int));
    ofs.write((const char*)&m2.age, sizeof(int));

    // 获取字符串长度
    size_t size1 = m1.name.size();
    size_t size2 = m2.name.size();

    // 写入字符串长度
    ofs.write((const char*)&size1, sizeof(size1));
    ofs.write((const char*)&size2, sizeof(size2));

    // 写入字符串
    ofs.write(m1.name.c_str(), size1);
    ofs.write(m2.name.c_str(), size2);

    ofs.close();
}

// 读取文件
void test02() {
    std::ifstream ifs;
    ifs.open("test.txt", std::ios::in | std::ios::binary);
    if (!ifs.is_open()) {
        std::cout << "打开失败\n";
    }

    // 读取文件
    make m1, m2;

    ifs.read((char*)&m1.age, sizeof(int));
    ifs.read((char*)&m2.age, sizeof(int));

    // 读取字符串长度
    size_t size1, size2;
    ifs.read((char*)&size1, sizeof(size1));
    ifs.read((char*)&size2, sizeof(size2));

    // 读取字符串
    m1.name.resize(size1);
    m2.name.resize(size2);
    ifs.read(&m1.name[0], size1);
    ifs.read(&m2.name[0], size2);

    std::cout << "name:" << m1.name << " age:" << m1.age << '\n';
    std::cout << "name:" << m2.name << " age:" << m2.age << '\n';

    ifs.close();
}

auto main() -> int32_t {
    test01();
    test02();
    return static_cast<int>(0);
}