首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将C++矢量读写到文件

将C++矢量读写到文件
EN

Stack Overflow用户
提问于 2010-03-18 19:51:53
回答 6查看 43.9K关注 0票数 18

对于一些图形工作,我需要尽可能快地读取大量数据,理想情况下,我希望直接读取数据结构并将其写入磁盘。基本上,我加载了各种文件格式的3d模型,加载时间太长,所以我想将它们以“准备好的”格式写出来,作为缓存,以便在程序的后续运行中加载得更快。

这样做安全吗?我担心的是直接读取向量的数据?我已经删除了错误检查,硬编码4作为整数的大小,等等,所以我可以给出一个简短的工作示例,我知道这是糟糕的代码,我的问题是,在c++中,将整个结构直接读取到向量中是否安全?我相信是这样的,但是当你开始低级直接处理原始内存时,c++有很多陷阱和未定义的行为。

我意识到数字的格式和大小可能会在不同的平台和编译器之间改变,但这只会被相同的编译器程序读取和写入,以缓存稍后运行相同程序时可能需要的数据。

#include <fstream>
#include <vector>

using namespace std;

struct Vertex
{
    float x, y, z;
};

typedef vector<Vertex> VertexList;

int main()
{
    // Create a list for testing
    VertexList list;
    Vertex v1 = {1.0f, 2.0f,   3.0f}; list.push_back(v1);
    Vertex v2 = {2.0f, 100.0f, 3.0f}; list.push_back(v2);
    Vertex v3 = {3.0f, 200.0f, 3.0f}; list.push_back(v3);
    Vertex v4 = {4.0f, 300.0f, 3.0f}; list.push_back(v4);

    // Write out a list to a disk file
    ofstream os ("data.dat", ios::binary);

    int size1 = list.size();
    os.write((const char*)&size1, 4);
    os.write((const char*)&list[0], size1 * sizeof(Vertex));
    os.close();


    // Read it back in
    VertexList list2;

    ifstream is("data.dat", ios::binary);
    int size2;
    is.read((char*)&size2, 4);
    list2.resize(size2);

     // Is it safe to read a whole array of structures directly into the vector?
    is.read((char*)&list2[0], size2 * sizeof(Vertex));

}
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-03-18 20:17:11

正如Laurynas所说,std::vector被保证是连续的,所以这应该可以工作,但它可能是不可移植的。

在大多数系统上,sizeof(Vertex)将是12,但是填充结构的情况并不少见,因此sizeof(Vertex) == 16。如果您在一个系统上写入数据,然后在另一个系统上读取该文件,则无法保证它将正常工作。

票数 20
EN

Stack Overflow用户

发布于 2010-03-19 01:20:11

您可能会对Boost.Serialization库感兴趣。它知道如何将STL容器保存到磁盘或从磁盘加载STL容器,等等。对于您的简单示例来说,这可能有些过分,但是如果您在程序中执行其他类型的序列化,它可能会变得更有用。

下面是一些示例代码,它们实现了您想要的功能:

#include <algorithm>
#include <fstream>
#include <vector>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>

using namespace std;

struct Vertex
{
    float x, y, z;
};

bool operator==(const Vertex& lhs, const Vertex& rhs)
{
    return lhs.x==rhs.x && lhs.y==rhs.y && lhs.z==rhs.z;
}

namespace boost { namespace serialization {
    template<class Archive>
    void serialize(Archive & ar, Vertex& v, const unsigned int version)
    {
        ar & v.x; ar & v.y; ar & v.z;
    }
} }

typedef vector<Vertex> VertexList;

int main()
{
    // Create a list for testing
    const Vertex v[] = {
        {1.0f, 2.0f,   3.0f},
        {2.0f, 100.0f, 3.0f},
        {3.0f, 200.0f, 3.0f},
        {4.0f, 300.0f, 3.0f}
    };
    VertexList list(v, v + (sizeof(v) / sizeof(v[0])));

    // Write out a list to a disk file
    {
        ofstream os("data.dat", ios::binary);
        boost::archive::binary_oarchive oar(os);
        oar << list;
    }

    // Read it back in
    VertexList list2;

    {
        ifstream is("data.dat", ios::binary);
        boost::archive::binary_iarchive iar(is);
        iar >> list2;
    }

    // Check if vertex lists are equal
    assert(list == list2);

    return 0;
}

注意,我必须在boost::serialization名称空间中为您的Vertex实现一个serialize函数。这使序列化库知道如何序列化Vertex成员。

我浏览过boost::binary_oarchive源代码,它似乎直接从流缓冲读写原始向量数组数据。所以它应该是相当快的。

票数 11
EN

Stack Overflow用户

发布于 2010-03-18 19:54:37

std::vector保证在内存中是连续的,所以,是的。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2469531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档