2015-04-07 64 views
0

我想將對象的矢量保存到文件中。什麼是最有效的方法呢?我應該在程序啓動時加載整個矢量,在本地操作它,然後在程序退出或每次需要更改矢量內的某些內容時訪問文件保存它。將對象的矢量保存到C++文件中

另外,它甚至可以一次保存整個矢量,或者我需要一個一個保存元素?

+0

你是什麼意思的對象? –

+0

這取決於你想要使用它。 – zoska

+0

@ErikW,類對象 – foofaraw

回答

1

如果您的數據是POD(因此每個元素的大小相同),您可以使用以下想法。否則,以下想法可能很難輕易使用。

下面的代碼顯示了你「可以」使用「的ostream ::寫」把二進制數據輸出到文件中。矢量<>承諾對象在內存中是從前到後(或者從後到前),因此它們排列整齊並且相對緊湊以便傳輸。

讀回到內存是類似的,使用「istream :: read」。但是在這裏你需要分配緩衝1st。

在下面的代碼,我分配的6個對象寫,然後發現向量存儲器的開始,並與一個「寫」寫的所有6個對象。

有關讀,我實例化,並裝載6個對象到一個新的矢量(請注意,載體提供分配和實例使用默認構造函數的對象雨衣方式)。

如何將寫入操作中的對象數量傳遞給讀取?這可以從文件大小來計算。 (請參閱stat)

使用重新解釋鑄不是(通常)可以接受的,並且可以不是便攜式的。但有時你只是要做到這一點。

希望這個'邪惡'會提示一些更好的選擇。

我留在一些調試std :: cout的...希望你覺得他們有幫助。

編輯 - 4/8 - 清理代碼有點

 // create a vector of 6 clear elements to save to file 
     std::vector<Something> vec6W(6); // default ctor clears contents 

     // change several elements by init'ing them 
     vec6W[0].init(); 
     // [1] is clear (all 0's) 
     vec6W[2].init(); 
     vec6W[3].init(); 
     // [4] is clear (all 0's) 
     vec6W[5].init(); 

     std::cout << "    vec6W.size(): " << vec6W.size()  << std::endl; // 6 
     std::cout << "    sizeof(vec6W): " << sizeof(vec6W)  << std::endl; // 12 
     std::cout << "   sizeof(something): " << sizeof(Something) << std::endl; // 100 
     std::cout << "   sizeof(vec6W[3]): " << sizeof(vec6W[3]) << std::endl; // 100 

     //      #elements  bytes per element 
     std::streamsize nBytes = (vec6W.size() * sizeof(Something)); 
     std::cout << "      nBytes : " << nBytes << std::endl; // 600 

     // simulate a file using 
     std::stringstream ss; 

     // note size 
     std::cout << "    ss.str().size(): " << ss.str().size() << std::endl; // 0 

     // identify address of 1st element of vector 
     // cast to a 'const char*' for 'write()' method 
     const char* wBuff = reinterpret_cast<const char*>(&vec6W[0]); 

     // report address 
     std::cout << " static_cast<const void*>(wBuff): " << std::hex 
       << static_cast<const void*>(wBuff) << std::dec << std::endl; 

     //write vector to ss 
     ss.write(wBuff, nBytes); 

     std::cout << "\n note ss content size change " << std::endl; 
     std::cout << "   ss.str().size() : " << ss.str().size() << std::endl; 

     // ////////////////////////////////////////////////////////////////// 
     // build a vector of 6 clear elements to create buffer for read from file 
     std::vector<Something> vec6R(6); 

     // identify address of 1st element of vector 
     std::cout << "     &vec6R[0] : " << std::hex << (&vec6R[0]) << std::dec << std::endl; 

     char* rBuff = reinterpret_cast<char*>(&vec6R[0]); 

     // read vector from ss 
     (void)ss.read(rBuff, nBytes); // read back same number of bytes 

     // ////////////////////////////////////////////////////////////////// 
     // confirm vec6R matches what was written vec6W 
     int diff = memcmp(wBuff, rBuff, nBytes); 

     std::cout << (diff ? "FAILED" : "wBuff MATCHES rBuff: SUCCESS") << std::endl; 

     // now consider comparing vec6R to vec6W element by element 

可能有其他問題,當類有虛方法。

祝你好運。

編輯-----

指針可以處理,但創建額外的工作,和一些不對稱。

相關工作可能被稱爲「持久存儲」。

而且,存在着工具來簡化非POD數據(對不起,我忘了名字)的額外步驟

+0

經過一點研究之後,我發現一次保存整個矢量對於'編程'級別來說是一種矯枉過正的行爲,並且逐個挑選對象並將它們作爲字符串保存在.dat文件的單獨行中。我一定會在未來的嘗試中感謝您的回答。 – foofaraw

1

這個問題沒有單一的答案。

適當的方法取決於你的應用程序,爲什麼它是保存文件,什麼將與文件來實現的需要。例如,打算在另一個程序中打開並且被人理解的文件可能與僅保存程序狀態的文件(即,只有軟件程序需要理解它)非常不同地寫入。

最高效率取決於您的效率衡量標準。一些可能的措施包括寫入速度,閱讀速度,文件大小,寫入代碼的大小等等。並非所有這些事情都在一起 - 例如,歸檔程序可能選擇緩慢的方法來編寫文件,以實現快速的讀取速度。

通常情況下,寫對象的集合包括單獨寫的所有對象,再加上一些額外的簿記(如輸出對象的數量第一),特別是如果文件需要日後閱讀。但是,更智能的算法可能會從一組對象中獲取某種摘要數據。例如,假定一個包含整數1到20的矢量。一種書寫方式是寫出全部20個值。另一種是簡單地發出字符串「1-20」。

+0

感謝您的回答@Peter我想將我的數據保存爲二進制文件。另外,我將在單次運行中多次訪問文件中的數據,所以我認爲對我來說最好的選擇是在啓動時讀取文件並在退出時寫入。我是對的? – foofaraw

+0

那麼,在啓動時讀取一次文件並在終止時再次寫出文件是一種選擇。雖然沒有單一的「最佳選擇」,但有設計選擇,每個設計選擇都有好的和壞的結果。不是絕對的,像「最好的」。還要小心二進制文件 - 並非所有的C++類類型都可以繼續作爲二進制文件寫入並重新讀入。 – Peter

+0

假設我想保存包含某些ID,用戶名,密碼等的用戶對象。什麼類型的文件我應該使用,如果不是二進制? – foofaraw