【问题标题】:Write and load vector of structs in a binary file c++在二进制文件c ++中写入和加载结构向量
【发布时间】:2015-02-13 04:30:28
【问题描述】:

我真的需要你的帮助。我的代码中有以下结构:

    struct Field{
        char name[20];
        int type;
        int length;
    };

    struct Record{
        vector<Field> structure;
        vector<string> info;
    };

我想要做的是将我的 struct Record 的向量存储在二进制文件中并成功将其加载回来。问题是我的结构里面有两个向量,它们给我带来了一些麻烦。你能帮帮我吗?

【问题讨论】:

标签: c++ vector struct binary


【解决方案1】:

您基本上只是编写将结构写入流的函数。首先,如果它是 POD,则写下结构的大小。

如果不是 POD,则写入每个元素的大小,然后写入元素的数据。

下面你可以看到writevecfield,它首先写入向量的大小。然后它将整个 POD 结构写入流。 writesvecstring 首先写入向量的大小。然后它遍历向量并写入:每个字符串的大小及其内容。

要阅读,则相反。 readvecfield 从文件中读取向量的大小,因为它是第一个写入的。读取后,我们调整向量的大小并将“字段”结构的“大小”数量读入新向量中。

要读取字符串,我们也执行相反的操作。 readvecstring 首先从文件中读取向量的大小。它将向量的大小调整为读取大小。接下来它循环“大小”次数,因为这是文件中字符串的数量。

然后我们读取字符串的大小,调整字符串的大小并将内容读入该字符串。然后我们将它添加到向量并移动到下一个字符串:首先读取大小,调整字符串大小,读取内容,添加到向量..

#include <fstream>
#include <vector>
#include <iostream>
#include <sstream>

using namespace std;


struct Field
{
    char name[20];
    int type;
    int length;
};

struct Record
{
    vector<Field> structure;
    vector<string> info;
};

void writevecfield(ostream& os, const vector<Field> &vec)
{
    typename vector<Field>::size_type size = vec.size();
    os.write((char*)&size, sizeof(size));
    os.write((char*)&vec[0], vec.size() * sizeof(Field));
}

void readvecfield(istream& is, vector<Field> &vec)
{
    typename vector<Field>::size_type size = 0;
    is.read((char*)&size, sizeof(size));
    vec.resize(size);
    is.read((char*)&vec[0], vec.size() * sizeof(Field));
}

void writevecstring(ostream& os, const vector<string> &vec)
{
    typename vector<string>::size_type size = vec.size();
    os.write((char*)&size, sizeof(size));

    for (typename vector<string>::size_type i = 0; i < size; ++i)
    {
        typename vector<string>::size_type element_size = vec[i].size();
        os.write((char*)&element_size, sizeof(element_size));
        os.write(&vec[i][0], element_size);
    }
}

void readvecstring(istream& is, vector<string> &vec)
{
    typename vector<string>::size_type size = 0;
    is.read((char*)&size, sizeof(size));
    vec.resize(size);

    for (typename vector<string>::size_type i = 0; i < size; ++i)
    {
        typename vector<string>::size_type element_size = 0;
        is.read((char*)&element_size, sizeof(element_size));
        vec[i].resize(element_size);
        is.read(&vec[i][0], element_size);
    }
}



void WriteRecord(ostream& out, const Record& r)
{
    writevecfield(out, r.structure);
    writevecstring(out, r.info);
}

void ReadRecord(istream& in, Record& r)
{
    readvecfield(in, r.structure);
    readvecstring(in, r.info);
}


int main()
{
    Record R;

    Field first = {"HELLO", 1, 20};
    Field second = {"WORLD", 2, 40};
    R.structure.push_back(first);
    R.structure.push_back(second);
    R.info.push_back("INFO FOR HELLO");
    R.info.push_back("INFO FOR WORLD");

    std::ofstream out("C:/Users/***/Desktop/Test.bin", std::ios::out | std::ios::binary);
    WriteRecord(out, R);
    out.close();

    Record RR;
    std::ifstream in("C:/Users/***/Desktop/Test.bin", std::ios::in | std::ios::binary);
    ReadRecord(in, RR);
    in.close();

    for (int i = 0; i < RR.structure.size(); ++i)
    {
        std::cout<<"Name:   "<<RR.structure[i].name<<"\n";
        std::cout<<"Type:   "<<RR.structure[i].type<<"\n";
        std::cout<<"Length: "<<RR.structure[i].length<<"\n";
        std::cout<<"INFO:   "<<RR.info[i]<<"\n\n";
    }
}

【讨论】:

  • 谁能给我解释一下 writevecfield 和 readvecfield 函数的第一行代码吗?
  • 为什么我们需要 Record 结构体?
  • @IanDzindo;该帖子解释了它在做什么.. 它执行typename vector&lt;Field&gt;::size_type size = vec.size();size_t size = vec.size() 相同.. 然后它执行os.write(&amp;size, sizeof(size_t))size 写入流。然后它执行os.write(&amp;vec[0], vec.size() * sizeof(Field))vec.size() amount of Field 从向量写入流。
  • 好的,谢谢,但是这里使用的 Record 结构是什么?
  • @IanDzindo 你看到被问的问题了吗?
【解决方案2】:

我使用类似c的句子来处理。关键是你只需要找到第一个vec数据的地址,而不是使用相邻的缓冲区将它们写入文件。

bool storeStructVec(FILE *fpOut, const vector<Field> &vec)
{
    unsigned int nSize = vec.size();
    if (nSize != fwrite(&vec[0],sizeof(Field),nSize,fpOut))
         return false;
    else return true;
}

【讨论】:

  • 没有任何解释的答案被认为是低质量的。尝试添加一些解释。
猜你喜欢
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多