簡體   English   中英

C++:當數據復雜時讀/寫二進制數據到文件

[英]C++ : Read/Write Binary data to file when data is complex

如果我還必須定義如何保存我的數據,我將如何將數據寫入/讀取到二進制文件?
我試圖將一些簡單的數據結構保存到二進制文件中。

例如,我有一個像這樣的結構向量:

struct Vertex
{
    x;
    y;
    z;
}

std::vector<Vertex> vertices;

我想將此向量保存到二進制文件中。

我知道如何使用ifstreamostream使用<<>>運算符輸出它,這些運算符可以重載以處理我的數據,但它們不能輸出二進制。

我也知道如何使用 .write() 以二進制形式寫入,但問題是我找不到一種方法來重載我需要的內容,以處理我的數據。

這是對類似問題的回答 雖然這在您的情況下沒問題,但請注意,如果您在結構中使用指針,這將不起作用。

指針的意思是:“在另一個內存段中加載了相關數據”,但實際上,它只包含內存的地址。 然后寫操作會保存這個內存位置。 當您將其加載回來時,內存中保留您想要的信息的可能性很小。

人們通常做的是創建一個序列化機制。 將一個方法添加到您的結構中,或者編寫另一個函數,將您的結構作為參數並以您決定的特殊格式輸出包含數據的 char* 數組。 您還需要相反的函數來讀取文件並從二進制數據重新創建結構。 你應該看看boost::serialization ,它處理這個非常常見的編程問題。

一種方法(不一定是最好的)是寫入數據,使用您選擇的任何二進制寫入函數,例如

write(fd,data,size);

但是將“數據”作為結構傳遞。

例如

Vertex data;
data.x = 0;
etc...
write(fd,(char*)&data,sizeof(data));

這會將結構視為字符數組,然后將它們寫入文件。 讀回應該是上面的相反。

請注意,使用向量(它們是動態分配的並且我在內存中的奇怪位置有奇怪的東西)並沒有真正的好方法,因此我建議使用結構數組。

我一直在尋找一種有效且緊湊的方式來永久存儲數據,但找不到任何可執行的最小示例,因此我為您整理了它。

該解決方案的美妙之處在於能夠隨心所欲地處理“向量”中的數據並隨心所欲地擴展“結構”(只需稍作更改)

這樣,在內存中表示的“向量”被傳輸到驅動器,然后再通過“std::vector”提供的“data()”方法返回。

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#define FILENAME "data.bin"

struct Vertex
{
    size_t x{};
    size_t y{};
    std::string z{};
};

void writeVectorToBinary(std::vector<Vertex> &v);
void readVectorFromBinary(std::vector<Vertex> &v);
void printVector(std::vector<Vertex> &v);

int main()
{
std::vector<Vertex> vertices;
vertices.push_back({1,2,"three"});
vertices.push_back({4,5,"six"});

writeVectorToBinary(vertices);
printVector(vertices);
readVectorFromBinary(vertices);
printVector(vertices);

std::cin.get();
return 0;
}


void writeVectorToBinary(std::vector<Vertex> &v)
{
  size_t size = v.size();
  //Open Binary file, to write out data
  std::ofstream file(FILENAME, std::ios::binary);
  if(!file)
    std::cout << "Something went wrong" << std::endl;
  //Store/Write the vector size
  file.write(reinterpret_cast<const char*>(&size), sizeof(size));
  //Store/Write the data of the vector out
  file.write(reinterpret_cast<const char*>(v.data()), sizeof(v[0])*size);
  //Close binary file
  file.close();
}

void readVectorFromBinary(std::vector<Vertex> &v)
{
//Clear Vector just for the proof of concept
v.clear();
size_t size{};
//Open Binary file to read in data
std::ifstream file(FILENAME,std::ios::binary);
if(!file)
  std::cout << "Something went wrong" << std::endl;
//Read the vector size
file.read(reinterpret_cast<char*>(&size), sizeof(size));
//Resize vector now that its known
v.resize(size);
//Read vector data in
file.read(reinterpret_cast<char*>(v.data()), sizeof(v[0])*size);
//Close binary file
file.close();
}

void printVector(std::vector<Vertex> &v)
{
  for(size_t i{}; i < v.size(); ++i ){
    std::cout << "\n------Vector" << i << "--------" << std::endl;
    std::cout << v[i].x << std::endl;
    std::cout << v[i].y << std::endl;
    std::cout << v[i].z << std::endl;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM