简体   繁体   English

如何将 stl 容器保存在磁盘中?

[英]How to save stl container in disk?

I have a stl container, which save a lot of data.我有一个 stl 容器,可以保存大量数据。

for example, the definition is:例如,定义是:

std::unordered_map<std::string, std::vector<int32_t> > m;  // there are 10 million data in this container

what i want is to save it in a file, then next time, i can read this file to recover it quickly.我想要的是将它保存在一个文件中,然后下一次,我可以读取这个文件以快速恢复它。

i think the normal way, like:我认为正常的方式,如:

write(&m, sizeof(m))

doesn't work, because it only save the pointer.不起作用,因为它只保存指针。

so, how can i save it in file and recover it by read file?那么,我怎样才能将它保存在文件中并通过读取文件来恢复它?

Choose a file format, eg a simple list, iterate over your container and write each element:选择一种文件格式,例如一个简单的列表,遍历您的容器并写入每个元素:

for (const auto &el : m) {
    file << el.first << '\n' << el.second.size() << '\n';
    for (const auto &vecEl : el.second) {
        file << vecEl << '\n';
    }
}

Then you can read the file with然后你可以读取文件

std::string first;
std::size_t count;
while (std::getline(file, first) && file >> count) {
    std::vector<int32_t> v(count);
    for (auto &vecEl : v) {
        file >> vecEl;
    }
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    m[first] = v;
}

This is just a sketch.这只是一个草图。 You probably have to add error checks.您可能必须添加错误检查。

Given you're not keen to use boost, the lowest-effort lowest-reusability option is something like:鉴于您不热衷于使用 boost,最低努力最低可重用性选项类似于:

// some support macros for easy error detection/handling...

#define FATAL(MSG) \
    do { \
         std::cerr << "FATAL ERROR at line " << __LINE__ << ":\n" \
             "    " << MSG << '\n'; \
         exit(EXIT_FAILURE); \
    } while (false)

#define ASSERT(X, MSG) \
     do { \
         if (X) break; \
         FATAL("ASSERT(" #X ") FAILED; " << MSG); \
     } while (false)

// output your container to disk...

if (std::ofstream out{filename}) {
    for (auto& [key, value] : m) {
        out << key.size() << ' ';
        out.write(key.data(), key.size();
        out << ' ' << value.size();
        for (auto& i : values)
            out << ' ' << i;
        out >> '\n';
    }
    ASSERT(out, "failed while writing to " << filename);
}
else
    FATAL("failed to create " << filename);

This just creates a file with lines like:这只会创建一个文件,其中包含以下行:

13 A 13 char str 5 1 2 3 4 5

The leading 13 means you know how many characters are in the string before parsing it, which saves us the trouble of coming up with some escaping and terminator convention, or the risk of not having one (eg assuming the string doesn't embed a newline is risky in general).前导 13 表示您在解析字符串之前就知道字符串中有多少个字符,这样可以省去我们想出一些 escaping 和终止符约定的麻烦,或者没有一个的风险(例如,假设字符串没有嵌入换行符一般是有风险的)。 The first '5' indicates the array length, only needed to speed loading, as it lets you reserve enough memory up front, which may be faster than using .push_back and having to resize during loading of an array.第一个“5”表示数组长度,只需要加快加载速度,因为它可以让您预先预留足够的 memory,这可能比使用.push_back更快,并且在加载数组期间必须resize

Reading the file then becomes:读取文件则变为:

if (std::ifstream in{filename}) {
    size_t len;
    while (in >> len) {
        std::string key;
        key.resize(len);
        ASSERT(in.read(key.data(), len));
        ASSERT(in >> len);
        std::vector<int32_t> v;
        v.reserve(len);
        while (len--) {
            ASSERT(in >> num);
            v.push_back(num);
        }
    }
    ASSERT(out.eof(), "failed to parse string size");
    m[std::move(key)] = std::move(v);
}
else
    FATAL("failed to open " << filename);

I haven't tested this, so use/test/debug as needed....我还没有测试过这个,所以根据需要使用/测试/调试....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM