无法在二进制文件中存储动态数组

问题描述:

我需要能够将数组存储在结构中,然后将结构保存为字节文件。问题是我需要数组是动态的。指针数组不存在,因为当涉及到保存时,只保存指针并且矢量不起作用。这是我正在使用的当前设置的一个示例。无法在二进制文件中存储动态数组

struct GenerationBase 
{ 
    //float value[];    // Will override data currently in ram 
    //float value[10];    // Dose not work as it needs to have a dynamic size 
    //float* value;     // Will only save the pointer value 
    //std::vector<float> value;  // Dose not work for some reason 
}; 

template<typename T> 
void write_to_file(std::ofstream& stream, T data) 
{ 
    stream.write(reinterpret_cast<const char*>(&data), sizeof(T)); 
} 

int main() 
{ 
    const char* file = "file.txt"; 

    GenerationBase write{}; 

    std::ofstream stream_write(file, std::ios::binary); 

    write_to_file(stream_write, write); 

    stream_write.close(); 

} 
+1

建议使用'德/ Serialiazation'.http://www.boost.org/doc/libs/1_36_0/libs/serialization/doc/index.html – Raindrop7

+0

的sizeof(T)是一个编译时的事情 - 如果你的数组是动态的,它不是一个选项 – WindyFields

+0

一个'vector'比简单的数据阵列更复杂。你不能只拿它的地址。 – AndyG

评论中的所有注释都是正确的 - 您必须使用一些库进行序列化。 protobuf,boost :: serialization是很好的二进制格式,JSON和XML是文本存储的不错选择。

这种方法存在更多的基本问题,但是你的结构的字节组成依赖于很多东西:编译器,字节序,32位或64位体系结构。这意味着您不能简单地将C++数据结构的字节内容存储在文件中。

当从“运行时而不是编译时确定大小”的意义上使用动态大小的结构时,可以使用一个未指定大小的数组,如float value[]作为该结构的最后一个成员。但是请注意,您必须“手动”为结构分配适当大小的内存。 C就是这种情况,C++也是如此。不幸的是,使用运算符new时手动定义大小非常棘手,因为new使用该类型来确定大小,而不是任何运行时值。所以你可能会使用mallocfree,这在C++中看起来不太合适。

更简单的解决方案是使用std::vector,而不是写入结构存储器的转储,而是写入向量的内容。

无论如何,对于您遵循的每种方法,您还必须将数组中元素的数量写入文件;否则 - 至少如果您将几个这样的结构体顺序写入同一个文件中 - 您可能会丢失信息,该文件中存储的(动态)数组实际具有多少个元素。那么当然,读入过程必须考虑这个数字并相应地创建/修改structs

请参阅以下代码,它演示了(1)向量方法和(2)具有可变大小方法的结构。希望它以某种方式帮助。

struct GenerationBase_UsingVector 
{ 
    std::vector<float> value; 

    void write(std::ofstream &w) const { 
     size_t num_elems = value.size(); 
     w.write((const char*)&num_elems, sizeof(num_elems)); 
     w.write((const char*)value.data(), num_elems*sizeof(float)); 
    } 

    void read(std::ifstream &r) { 
     size_t num_elems; 
     r.read((char *)&num_elems, sizeof(num_elems)); 
     float f; 
     while (num_elems--) { 
      r.read((char *)&f, sizeof(f)); 
      value.push_back(f); 
     } 
    } 
}; 

struct GenerationBase_PlainArray 
{ 
    size_t num_elems; 
    float value[]; 

    static GenerationBase_PlainArray* create(size_t num_elems) 
    { 
     GenerationBase_PlainArray* result = (GenerationBase_PlainArray*)malloc(sizeof(GenerationBase_PlainArray) + num_elems*sizeof(float)); 
     result->num_elems = num_elems; 
     return result; 
    } 

    static struct GenerationBase_PlainArray* newFromStream(std::ifstream &r) { 
     size_t num_elems; 
     r.read((char *)&num_elems, sizeof(num_elems)); 
     GenerationBase_PlainArray* result = GenerationBase_PlainArray::create(num_elems); 
     r.read((char *)result->value, num_elems*sizeof(float)); 
     return result; 
    } 

    void write(std::ofstream &w) const { 
     w.write((const char*)&num_elems, sizeof(num_elems)); 
     w.write((const char*)value, num_elems*sizeof(float)); 
    } 
}; 

int main() { 


    GenerationBase_UsingVector gb_vector_forwrite; 
    gb_vector_forwrite.value.push_back(1.0); 
    gb_vector_forwrite.value.push_back(2.0); 
    gb_vector_forwrite.value.push_back(3.0); 
    gb_vector_forwrite.value.push_back(4.0); 
    gb_vector_forwrite.value.push_back(5.0); 
    gb_vector_forwrite.value.push_back(6.0); 

    std::ofstream write("test.bin", std::ios::binary); 
    gb_vector_forwrite.write(write); 
    write.close(); 

    GenerationBase_UsingVector gb_vector_forread; 
    std::ifstream read("test.bin", std::ios::binary); 
    gb_vector_forread.read(read); 
    read.close(); 

    for (auto f : gb_vector_forread.value) { 
     cout << f << endl; 
    } 

    GenerationBase_PlainArray* gb_array_forwrite = GenerationBase_PlainArray::create(6); 
    gb_array_forwrite->value[0] = 1.0; 
    gb_array_forwrite->value[1] = 2.0; 
    gb_array_forwrite->value[2] = 3.0; 
    gb_array_forwrite->value[3] = 4.0; 
    gb_array_forwrite->value[4] = 5.0; 
    gb_array_forwrite->value[5] = 6.0; 

    std::ofstream write2("test2.bin", std::ios::binary); 
    gb_array_forwrite->write(write2); 
    write2.close(); 
    free(gb_array_forwrite); 

    std::ifstream read2("test2.bin", std::ios::binary); 
    GenerationBase_PlainArray *gb_array_forread = GenerationBase_PlainArray::newFromStream(read2); 
    read2.close(); 

    for (int i=0; i<gb_array_forread->num_elems; i++) { 
     cout << gb_array_forread->value[i] << endl; 
    } 
    free(gb_array_forread); 

}