Запись вектора на основе структуры в файл и чтение её обратно, 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 шт):
всё я решил свою задач, ниже я привёл мой кривой код:
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);
}
Лучше использовать готовые библиотеки сериализации/десериализации. Например, 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";
}
}