Запись / чтение структуры из файла в std :: vector <> [duplicate]

0

Я успешно выполнил ответ, размещенный здесь, чтобы написать структуру (типа image_info_t) в файл. Я повторяю процесс в цикле для N числа image_info_t и все данные сериализуются и добавляются в файл правильно.

Теперь мне нужно прочитать файл, но мне нужно уметь читать произвольное число, M, image_info_t structs для чтения из файла (все в порядке). В приведенном выше ответе явно жестко указывается количество структур для чтения из файла (т. student_t master[3];). Однако мне нужно, чтобы этот номер был динамичным.

Я прочитал здесь, что "C++ стандарт требует, чтобы массивы использовали либо целочисленный литерал, либо целочисленную константу при объявлении его размера. Используйте <vector> вместо этого"

Мой вопрос: как я могу это сделать? Как я могу прочитать набор структур image_info_t из файла в std::vector?

Вот мой текущий (нерабочий) код, который я использую для чтения данных image_info_t из файла.

 std::ifstream input_file(path, std::ios::binary);
 const int kpts_size = kpts.size();
 feature_t master[kpts_size];  //DOES NOT WORK. If I change to 'feature_t master[10];' it works.
 input_file.read((char*)&master, sizeof(master));
 input_file.close();

Примечание. Это не вопрос нарушения прав доступа и не связан с ответом "Возможный дубликат". Когда вы помечаете его как таковой, люди перестают читать мой вопрос, который, безусловно, никому не помогает.

  • 0
    Легко, ищите StackOverflow для "c ++ parse read file".
  • 1
    Вызывающе не обманщик.
Показать ещё 6 комментариев
Теги:
file
struct

2 ответа

1
Лучший ответ
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>


//Some kind of structure containing many sample data types..
typedef struct image_info
{
    char image_type;
    std::uint32_t md5_hash;
    std::string image_name;
    std::vector<std::uint8_t> bytes;
} image_info_t;


//Used for writing the above structure to a stream..
std::ostream& operator << (std::ostream& os, const image_info &entry)
{
    std::size_t image_name_size = entry.image_name.size();
    std::size_t image_bytes_size = entry.bytes.size();

    os.write(&entry.image_type, sizeof(entry.image_type));
    os.write(reinterpret_cast<const char*>(&entry.md5_hash), sizeof(entry.md5_hash));
    os.write(reinterpret_cast<const char*>(&image_name_size), sizeof(image_name_size));
    os.write(entry.image_name.c_str(), entry.image_name.size());
    os.write(reinterpret_cast<const char*>(&image_bytes_size), sizeof(image_bytes_size));
    os.write(reinterpret_cast<const char*>(&entry.bytes[0]), entry.bytes.size());
    return os;
}

//Used for reading the above structure from a stream..
std::istream& operator >> (std::istream& is, image_info &entry)
{
    std::size_t image_name_size = 0;
    std::size_t image_bytes_size = 0;

    is.read(&entry.image_type, sizeof(entry.image_type));
    is.read(reinterpret_cast<char*>(&entry.md5_hash), sizeof(entry.md5_hash));
    is.read(reinterpret_cast<char*>(&image_name_size), sizeof(image_name_size));

    entry.image_name.resize(image_name_size);
    is.read(&entry.image_name[0], image_name_size);
    is.read(reinterpret_cast<char*>(&image_bytes_size), sizeof(image_bytes_size));

    entry.bytes.resize(image_bytes_size);
    is.read(reinterpret_cast<char*>(&entry.bytes[0]), image_bytes_size);
    return is;
}

//Used for writing an array/vector of the above structure to a stream..
std::ostream& operator << (std::ostream& os, const std::vector<image_info> &entry)
{
    std::size_t entry_size = entry.size();
    os.write(reinterpret_cast<const char*>(&entry_size), sizeof(entry_size));
    for (std::size_t i = 0; i < entry_size; ++i)
        os << entry[i];

    return os;
}

//Used for reading an array/vector of the above structure from a stream..
std::istream& operator >> (std::istream& is, std::vector<image_info> &entry)
{
    std::size_t entry_size = 0;
    is.read(reinterpret_cast<char*>(&entry_size), sizeof(entry_size));
    entry.resize(entry_size);
    for (std::size_t i = 0; i < entry_size; ++i)
        is >> entry[i];
    return is;
}

int main()
{
    std::vector<image_info_t> outdata;
    std::vector<image_info_t> indata;
    image_info_t one;
    image_info_t two;

    one.image_name = "one";
    one.image_type = 'a';
    one.md5_hash = 1;
    one.bytes.push_back(0);

    two.image_name = "two";
    two.image_type = 'b';
    two.md5_hash = 2;
    two.bytes.push_back(1);

    outdata.push_back(one);
    outdata.push_back(two);

    std::fstream out("C:/Users/School/Desktop/Image_Info_T.bin", std::ios::out | std::ios::binary);

    if (out.is_open())
    {
        out << outdata;
        out.close();
    }

    std::fstream in("C:/Users/School/Desktop/Image_Info_T.bin", std::ios::in | std::ios::binary);

    if (in.is_open())
    {
        in >> indata;
    }

    std::cout<<indata[0].image_name<<"    "<<indata[1].image_name;
}
  • 0
    это выглядит действительно многообещающе. Я получаю две ошибки компиляции: (а) в строке os << *it; указание Invalid operands to binary expression ('std::istream') and 'value_type' (aka image image_info) . Также (2) строка os << *it; состояния: Invalid operand binary expression ('std::ostream') and 'const image_info' . Есть идеи??
  • 0
    У вас не должно было быть никаких ошибок .. Он компилируется и запускается. Во всяком случае, я удалил итераторы и вместо этого использовал оператор индекса. Это должно работать для вас сейчас.
Показать ещё 1 комментарий
0

Если вы хотите избежать использования вектора, вы можете инициализировать свой массив, выполнив следующие действия:

feature_t* master = new feature_t[kpts.size()];
//code
delete[] master;

Альтернативно, с помощью вектора вы можете просто создать вектор feature_t, IE:

std::vector<feature_t> master;

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

feature_t temp;
while (getline(file, str))
{
    temp.a = ...;
    temp.b = ...;
    master.push_back(temp);
}

В C new будет заменен malloc (или одной из его производных функций), поэтому вы будете использовать:

feature_t* master = malloc(sizeof(master) * kpts.size());
//code
free(master);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню