2014-10-04 128 views
-1

我想讀取一個數組對象(數組是一個類,我已經使用讀取和寫入函數來讀取和寫入二進制文件。將不會從文件中正確出於某種原因讀取,這是寫功能:C++寫入和讀取對象到二進制文件

void writeToBinFile(const char* path) const 
    { 
     ofstream ofs(path, ios_base::out | ios_base::app | ios_base::binary); 
     if (ofs.is_open()) 
     { 
      ostringstream oss; 
      for (unsigned int i = 0; i < m_size; i++) 
      { 
       oss << ' '; 
       oss << m_data[i]; 
      } 
      ofs.write(oss.str().c_str(), oss.str().size()); 
     } 
    } 

這是讀功能:

void readFromBinFile(const char* path) 
    { 
     ifstream ifs(path, ios_base::in | ios_base::binary || ios_base::ate); 
     if (ifs.is_open()) 
     { 
      stringstream ss; 
      int charCount = 0, spaceCount = 0; 
      ifs.unget(); 
      while (spaceCount != m_size) 
      { 
       charCount++; 
       if (ifs.peek() == ' ') 
       { 
        spaceCount++; 
       } 
       ifs.unget(); 
      } 
      ifs.get(); 
      char* ch = new char[sizeof(char) * charCount]; 
      ifs.read(ch, sizeof(char) * charCount); 
      ss << ch; 
      delete[] ch; 
      for (unsigned int i = 0; i < m_size; i++) 
      { 
       ss >> m_data[i]; 
       m_elementCount++; 
      } 
     } 
    } 

這些都是類字段:

T* m_data; 
unsigned int m_size; 
unsigned int m_elementCount; 

我用下面的代碼進行編寫,然後讀取(1個執行讀取另一個寫入):

Array<int> arr3(5); 
    //arr3[0] = 38; 
    //arr3[1] = 22; 
    //arr3[2] = 55; 
    //arr3[3] = 7; 
    //arr3[4] = 94; 
    //arr3.writeToBinFile("binfile.bin"); 
    arr3.readFromBinFile("binfile.bin"); 
    for (unsigned int i = 0; i < arr3.elementCount(); i++) 
    { 
     cout << "arr3[" << i << "] = " << arr3[i] << endl; 
    } 

現在的問題是在readFromBinFile功能,它會停留在一個無限循環和PEEK ()返回-1由於某種原因,我不明白爲什麼。 另請注意我正在使用空格寫入二進制文件,以便在每個元素之間建立一個屏障,這樣我就可以知道區分數組中的對象,並在寫入開始時還有一個空間,以便在先前存儲的二進制數據在該文件中的數組二進制數據。

+0

@JoachimPileborg我不使用它的二進制文件本身 – dikson231 2014-10-04 21:46:05

+0

爲什麼你在開始閱讀任何東西之前調用'unget'? – 2014-10-04 21:47:57

+1

在讀取函數中,你有這樣的:'ss << ch;'可能你打算'ss >> ch;'? – Boris 2014-10-04 21:48:23

回答

1

在我看來,最主要的問題是您可以使用可變大小的文本格式編寫固定大小的二進制數據。如果你堅持純粹的二進制形式,它可能會更簡單。

而是寫入字符串流,然後編寫輸出到實際的文件,只是二進制數據直接寫入到文件中:

ofs.write(reinterpret_cast<char*>(m_data), sizeof(m_data[0]) * m_size); 

然後讀取數據時做類似的事情。


爲此,在寫入實際數據之前,您當然需要首先保存數組/向量中的條目數。

所以實際的寫入功能可以簡單到

void writeToBinFile(const char* path) const 
{ 
    ofstream ofs(path, ios_base::out | ios_base::binary); 
    if (ofs) 
    { 
     ofs.write(reinterpret_cast<const char*>(&m_size), sizeof(m_size)); 
     ofs.write(reinterpret_cast<const char*>(&m_data[0]), sizeof(m_data[0]) * m_size); 
    } 
} 

而且讀取功能

void readFromBinFile(const char* path) 
{ 
    ifstream ifs(path, ios_base::in | ios_base::binary); 
    if (ifs) 
    { 
     // Read the size 
     ifs.read(reinterpret_cast<char*>(&m_size), sizeof(m_size)); 

     // Read all the data 
     ifs.read(reinterpret_cast<char*>(&m_data[0]), sizeof(m_data[0]) * m_size); 
    } 
} 

取決於你如何定義m_data您可能需要閱讀的實際前要分配給它的內存數據。


哦,如果你想在數組的最後追加數據(但你爲什麼會在您顯示當前的代碼,你重寫整個數組反正)你寫的大小之初,尋求結束,然後寫入新的數據。

+0

在我的其他問題我用一個類似的技術,只是寫整個對象http://stackoverflow.com/questions/26196682/c-reading-and-writing-objects-to-binary-files?noredirect=1#comment41078380_26196682是除了你將字段寫成字符指針而不是對象本身之外,還有什麼不同? – dikson231 2014-10-04 22:03:48

+0

@ dikson231當你說「編寫整個對象」時,你的意思是一個完整的類的實例嗎?如果是的話,那麼你需要小心,因爲如果類包含不起作用的指針,並且如果類包含一個虛擬表(即,如果你的類或父類具有虛函數),那麼它也不會很好地工作。 – 2014-10-04 22:06:49

+0

這就是我的意思,所以在你的解決方案,它會工作?還有一些關於你的實現的問題,static_cast是不是用於在指針類型之間進行轉換?另外我知道這是脫離主題的問題,但C++風格轉換到C風格轉換(char *)之間的任何區別?使用sizeof(m_data [0])不會返回數組中單個對象的大小嗎?你不需要寫sizeof(m_data)來獲得整個數組的大小嗎? – dikson231 2014-10-04 22:18:06