jco*_*der 17 c++ file-io vector
对于某些图形工作,我需要尽快读取大量数据,理想情况下是直接读取和写入数据结构到磁盘.基本上我有各种各样的文件格式的3D模型,加载时间太长,所以我想把它们以"准备好"的格式写出来作为缓存,在后续的程序运行中加载速度要快得多.
这样做是否安全?我担心的是直接读入载体的数据?我已经删除了错误检查,硬编码4作为int的大小等等,所以我可以给出一个简短的工作示例,我知道这是错误的代码,我的问题是如果在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));
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*der 20
正如Laurynas所说,std::vector保证是连续的,所以它应该起作用,但它可能是不可移植的.
在大多数系统中,sizeof(Vertex)将是12,但结构被填充并不罕见,所以sizeof(Vertex) == 16.如果您要在一个系统上写入数据然后在另一个系统上读取该文件,则无法保证它能正常工作.
Emi*_*ier 10
您可能对Boost.Serialization库感兴趣.它知道如何在磁盘上保存/加载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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我必须在命名空间中serialize为您实现一个函数.这使序列化库知道如何序列化成员.Vertexboost::serializationVertex
我浏览了boost::binary_oarchive源代码,它似乎直接从/向流缓冲区读取/写入原始向量数组数据.所以应该很快.