views:

667

answers:

4

Hi ,

I want to write a structure which has a list of integer id. The list can be of varying length.

typedef  struct ss_iidx_node {
    int totalFreq;
    vector < int > docIDList;
}s_iidx_node;

Now, I wish to write this structure in a file and read it back. How can I do it?

Wrting is done:

fwrite(&obj,sizeof(s_iidx_node),1,dat_fd2);

When I read it back, it gives garbage value. It seems it storing only the strating and ending position of stl vector...which on reading is garbage? Any idea how to do it

Thanks

+2  A: 

Though I'd rather see an approach based on an explicit serialisation, you could try:

fwrite(&obj.totalFreq,sizeof(int),1,dat_fd2);
fwrite(&obj.docIDList[0],sizeof(int),obj.totalFreq,dat_fd2);

Assuming totalFreq == docIDList.size(), it's a spurious variable, so a better implementation would be:

size_t size=obj.docIDList.size();
fwrite(&size,sizeof(size_t),1,dat_fd2);
fwrite(&obj.docIDList[0],sizeof(int),size,dat_fd2);

My preferred implementation would be:

size_t size=obj.docIDList.size();
fwrite(&size,sizeof(size_t),1,dat_fd2);
for (size_t i=0;i<size;i++)
{
    int id=obj.docIDList[i];
    fwrite(&id,sizeof(int),1,dat_fd2);
}
Dave Gamble
I like the second approach, instead of iterating over the list as this is time consuming. How do we read now? I used vectorType <code>docList(size); fread(</code> But, it gives error <code>(69961) malloc: * error for object 0x101570: double free * set a breakpoint in malloc_error_break to debug Bus error</code> – let-them-c 0 secs ago
got it thanks, I used vectorType docList(size); fread(
As all writes to a file pointer are buffered I would question your comments about "time cosuming". There is probably a small diference but not much and will probably be completely swolled by disk IO time.
Martin York
PS. Did you make sure the vector was large enough before reading data into the structure. Also note. By uisng a binary format your data will not be transferable to different platforms as size and endiannes(sp) may change.
Martin York
I mean by looping over the for loop, in my case size can be as big as million records... thanks for the info though
+2  A: 

The vector class is defined roughly like this:

template <typename T>
class vector {
  ...

  T* array; // pointer to the actual data, stored in a dynamically allocated array
  size_t arrayLength;
  ...

};

The actual data of the vector are stored in a dynamically allocated array. The vector class simply holds a pointer to that array. So your fwrite call only stores the contents of the vector class, not the contents of the array it points to.

You need to write out the actual elements of the vector instead.

jalf
+3  A: 

Your code is simply non-portable. It tries to treat object as a raw sequence of bytes, which is plainly undefined for non-POD objects in the C++ standard (and your struct is non-POD because it contains a member of a non-POD type std::vector).

What happens in practice is that vector class typically consists of 3 fields: pointer to beginning of data, size, and capacity. What you see are bytes constituting those values written into the file.

You should consider avoiding C-style file I/O entirely, and using C++ streams and Boost Serialization library instead - it supports STL collections out of the box.

Pavel Minaev
A: 

I tried this on VS2010 Beta1. Did not try on other compilers. Please check out.

class Employee
{
    private:
      int _empno;
      string _name;
public:
      Employee(int empno, string name) : _empno(empno), _name(name) { }
      Employee() : _empno(-1), _name("") { }
      virtual ~Employee() { }
      virtual int GetEmpId() const;
      virtual string GetName() const;
      friend ostream& operator<<(ostream& os, const Employee& emp);
};

class Manager : public Employee
{
    private:
      vector<Employee> Reportees;
    public:
      Manager() : Employee() { }
      Manager(int empno, const string& name) : Employee(empno, name) { }
      ~Manager() { }
      void InsertEmployees(const Employee& emp);
      friend ostream& operator<<(ostream& os, const Manager& manger);
};

void Manager::InsertEmployees(const Employee& emp)
{
      Reportees.push_back(emp);
}

ostream& operator<<(ostream& os, const Manager& manager)
{
       os << "Empid:" << manager.GetEmpId()
                << "|Name:" << manager.GetName() << endl;
      typedef vector<Employee>::const_iterator EmpIter;

      EmpIter iter = manager.Reportees.begin();<br>
      for ( ; iter != manager.Reportees.end(); ++iter)
      {
                Employee e = *iter;
                os << "Reportee" << endl;
                os << "Empid:" << e.GetEmpId()
                   << "|Name:" << e.GetName() << endl;
      }    
return os; 
}

int main()
{
ofstream data("data.txt");
ofstream bin_data("data.bin", ios::binary);

Employee e1(100, "Jagan");
Employee e2(101, "Nath");
Employee e3(102, "Sai");
Employee e4(103, "Pantula");

Manager m(104, "Neeraja");
m.InsertEmployees(e1);
m.InsertEmployees(e2);
m.InsertEmployees(e3);
m.InsertEmployees(e4);


data << m;
data.close();
bin_data.write(reinterpret_cast<char*>(&m), sizeof(m));

bin_data.close();
ReadDataFromFile();
bin_data.close();
}

void ReadDataFromFile()
{

ifstream bin_data("data.bin", ios::binary);

Manager m;

while (bin_data.read(reinterpret_cast<char*>(&m), sizeof(m)))
   cout << m;

}