Запись вектора на основе структуры в файл и чтение её обратно, c++

мне нужно записать структуру, которая содержит два массива с другими структурами в файл и считать его обратно, структура из заголовочного файл:

struct reg {
    std::vector<Object> objects;
    std::vector<EntVariant> ents;

    reg();
    reg(std::vector<Object> objects, std::vector<EntVariant> ents);
        
    template <typename T>
    void add(T&& item) {
        if constexpr (std::is_same_v<std::decay_t<T>, Object>) {
            objects.push_back(item);
            std::cout << "Added Object" << std::endl;
        }
        else {
            ents.push_back(item);
            std::cout << "Added Entity" << std::endl;
        }
    }

    void draw(sf::RenderWindow& window) const;

};

пример для сохранения:
reg reg1(std::vector<Object>{("./sprites/test.png","", sf::Vector2f(100, 100), sf::Vector2f(5, 2))},std::vector<EntVariant>())
И мне нужно что бы при чтении, то что прочиталось шло к примеру в переменную reg2 в main.cpp


Ответы (2 шт):

Автор решения: Matvey Shuwalov

всё я решил свою задач, ниже я привёл мой кривой код:

void saveObjVec(const std::vector<Object>& vec, const std::string& filename) {
    Logger logi;
    std::ofstream file(filename);

    if(!file.is_open()){
        logi.log(Logger::Level::Fatal, "Fatal error -3; File is not open -> " + filename);
    }

    for (auto& obj : vec)
    {
        file << obj.img_path <<";"<< obj.data << ";" << obj.pos.x << ";" << obj.pos.y << ";"<< obj.size.x << ";" << obj.size.y << ";" << obj.collision << std::endl;
    }
    file.close();
    logi.log(Logger::Level::Info, "Info -1; Log is closed -> " + filename);
}

std::vector<Object> loadObjVec(const std::string& filename) {
    Logger logi;
    std::vector<Object> vec;
    std::ifstream file(filename);
    if(!file.is_open()){
        logi.log(Logger::Level::Fatal, "Fatal error -3; File is not open -> " + filename);
    }

    std::string line;
    while (std::getline(file, line)){
        std::istringstream iss(line);
        sf::Vector2f size;
        std::string img_path;
        std::string data;
        sf::Vector2f pos;
        bool collision;
        char delimiter;
        if (std::getline(iss, img_path, ';') && std::getline(iss, data, ';')) {
        if ((iss >> pos.x) && (iss >> delimiter) && (delimiter == ';') &&
            (iss >> pos.y) && (iss >> delimiter) && (delimiter == ';') &&
            (iss >> size.x) && (iss >> delimiter) && (delimiter == ';') &&
            (iss >> size.y) && (iss >> delimiter) && (delimiter == ';') &&
            (iss >> collision)) {
                pos = {pos.x, pos.y};
                size = {size.x, size.y};
                vec.emplace_back(img_path, data, pos, size, collision);
            }
        }
    }
    return vec;
    file.close();
    logi.log(Logger::Level::Info, "Info -1; Log is closed -> " + filename);
}
→ Ссылка
Автор решения: FrozenM

Лучше использовать готовые библиотеки сериализации/десериализации. Например, JSON, XML (есть куча готовых решений). Если не нравится - Boost serialization, Qt serialization. Не нравится - бинарная сериализация. Нашел свой старый код, изменил на, как обычно использующийся Person, но не проверял. Примерно так можно сериализовать

#include <vector>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <cstdint>

// Пользовательский класс
class Person {
public:
    std::string name;
    int age;
    double height;

    // Конструктор для удобства
    Person(std::string n = "", int a = 0, double h = 0.0)
        : name(std::move(n)), age(a), height(h) {}
};

// Сериализация одного объекта Person
void serialize_person(const Person& p, std::ostream& out) {
    // Сохраняем длину имени и само имя
    uint64_t name_size = p.name.size();
    out.write(reinterpret_cast<const char*>(&name_size), sizeof(name_size));
    out.write(p.name.c_str(), static_cast<std::streamsize>(name_size));
    
    // Сохраняем числовые поля
    out.write(reinterpret_cast<const char*>(&p.age), sizeof(p.age));
    out.write(reinterpret_cast<const char*>(&p.height), sizeof(p.height));
}

// Десериализация одного объекта Person
Person deserialize_person(std::istream& in) {
    Person p;
    
    // Читаем длину имени
    uint64_t name_size;
    in.read(reinterpret_cast<char*>(&name_size), sizeof(name_size));
    
    // Читаем имя
    std::string name(name_size, '\0');
    in.read(&name[0], static_cast<std::streamsize>(name_size));
    p.name = name;
    
    // Читаем числовые поля
    in.read(reinterpret_cast<char*>(&p.age), sizeof(p.age));
    in.read(reinterpret_cast<char*>(&p.height), sizeof(p.height));
    
    return p;
}

// Сериализация вектора
void serialize_vector(const std::vector<Person>& vec, const std::string& filename) {
    std::ofstream out(filename, std::ios::binary);
    if (!out) throw std::runtime_error("Can't open file: " + filename);
    
    // Сохраняем количество элементов
    uint64_t size = vec.size();
    out.write(reinterpret_cast<const char*>(&size), sizeof(size));
    
    // Сериализуем каждый объект
    for (const auto& p : vec) {
        serialize_person(p, out);
    }
}

// Десериализация вектора
std::vector<Person> deserialize_vector(const std::string& filename) {
    std::ifstream in(filename, std::ios::binary);
    if (!in) throw std::runtime_error("Can't open file: " + filename);
    
    // Читаем количество элементов
    uint64_t size;
    in.read(reinterpret_cast<char*>(&size), sizeof(size));
    
    std::vector<Person> vec;
    vec.reserve(size);
    
    // Десериализуем каждый объект
    for (uint64_t i = 0; i < size; ++i) {
        vec.push_back(deserialize_person(in));
    }
    
    return vec;
}

// Пример использования
int main() {
    std::vector<Person> people = {
        {"Alice", 30, 170.5},
        {"Bob", 25, 185.2},
        {"Charlie", 35, 165.8}
    };
    
    // Сериализация
    serialize_vector(people, "people.bin");
    std::cout << "Vector serialized!\n";
    
    // Десериализация
    auto loaded_people = deserialize_vector("people.bin");
    std::cout << "Deserialized data:\n";
    for (const auto& p : loaded_people) {
        std::cout << p.name << ": " << p.age << " years, " 
                  << p.height << " cm\n";
    }
}
→ Ссылка