запись списка динамического массива в файл в двоичном виде> - PullRequest
0 голосов
/ 09 июля 2009

Я хочу написать структуру, в которой есть список целочисленных идентификаторов. Список может быть различной длины.

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

Теперь я хочу записать эту структуру в файл и прочитать ее обратно. Как я могу это сделать?

Wrting сделано:

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

Когда я читаю это обратно, это дает мусорное значение. Кажется, он хранит только стратификацию и конечную позицию вектора stl ... что при чтении является мусором? Любая идея, как это сделать

Спасибо

Ответы [ 4 ]

3 голосов
/ 09 июля 2009

Ваш код просто не переносимый. Он пытается обработать объект как необработанную последовательность байтов, которая явно не определена для объектов не POD в стандарте C ++ (и ваша структура не POD, потому что она содержит член типа не POD std::vector).

На практике происходит то, что векторный класс обычно состоит из 3 полей: указатель на начало данных, размер и емкость. Вы видите байты, составляющие эти значения, записанные в файл.

Вам следует полностью отказаться от файлового ввода-вывода в стиле C и использовать вместо этого потоки C ++ и Boost Serialization library - она ​​поддерживает коллекции STL из коробки.

2 голосов
/ 09 июля 2009

Класс векторов определяется примерно так:

template <typename T>
class vector {
  ...

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

};

Фактические данные вектора хранятся в динамически распределенном массиве. Класс вектор просто содержит указатель на этот массив. Таким образом, ваш fwrite вызов хранит только содержимое векторного класса, а не содержимое массива, на который он указывает.

Вместо этого вам нужно выписать фактические элементы вектора.

2 голосов
/ 09 июля 2009

Хотя я предпочел бы увидеть подход, основанный на явной сериализации, вы можете попробовать:

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

Предполагая, что totalFreq == docIDList.size (), это ложная переменная, поэтому лучшей реализацией будет:

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

Моя предпочтительная реализация будет:

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);
}
0 голосов
/ 09 июля 2009

Я пробовал это на VS2010 Beta1. Не примерял другие компиляторы. Пожалуйста, проверьте.

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;

}
...