2014-10-04 129 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