2009-06-14 3 views
1

У меня есть файл, который я хочу прочитать и записать в двоичный файл, используя записи. В начале у меня есть пустой файл, и я хочу добавить новую запись, но когда я использую функцию seekp, тогда местоположение находится в (-1), нормально? Потому что, когда я проверяю, я вижу, что он ничего не написал в файл. См. Код:Работа с файлами fstream в цепочке переполнения в C++

void Library::addBook(Book newBook) 
{ 
fstream dataFile; 
dataFile.open("BookData.dat", ios::in | ios::out); 
    if (!dataFile) 
    { 
     cerr << "File could not be opened" << endl; 
    } 

int hashResult = newBook.getId() % 4 + 1; // The result of the hash function 

    // Find the right place to place the new book 
    dataFile.seekg((hashResult - 1) * sizeof(Book), ios::beg); 

    Book readBook; 
    dataFile.read(reinterpret_cast<char*>(&readBook), sizeof(Book)); 

    // The record doesnt exist or it has been deleted 
    if (readBook.getId() == -1) 
    { 
     // The record doesnt exist 
     if (readBook.getIdPtr() == -1) 
     { 
      dataFile.seekp((hashResult - 1) * sizeof(Book)); 
      dataFile.write(reinterpret_cast<char*>(&newBook), sizeof(Book)); 

     } 
     // The record has been deleted or there is already such record with such hash function 
     // so we need to follow the pointer to the overflow file 
     else 
     { 
      newBook.setIsBookInData(false); // New book is in overflow file 
      overflowFile.seekg((readBook.getIdPtr() - 1) * sizeof(Book)); 
      overflowFile.read(reinterpret_cast<char*>(&readBook), sizeof(Book)); 
      // Follow the chain 
      while (readBook.getIdPtr() != -1) 
      { 
       overflowFile.seekg((readBook.getIdPtr() - 1) * sizeof(Book)); 
       overflowFile.read(reinterpret_cast<char*>(&readBook), sizeof(Book)); 
      } 
      readBook.setIdPtr(header); // Make the pointer to point to the new book 
      overflowFile.seekp((header - 1) * sizeof(Book)); 
      overflowFile.write(reinterpret_cast<char*>(&newBook), sizeof(Book)); 
      header++; 
     } 
    } 

Если кто-нибудь может сказать мне, почему я не могу написать что-либо в файл, я действительно его приправлю.

Спасибо заранее,

Грег

+0

:(Никто не знает, как его решить? – 2009-06-14 17:12:11

+0

Если это не домашнее задание, то почему бы вам не использовать существующие решения, например, «Boost.Serialization», если вам нужна сериализация «Буферы протокола Google» для обмена двоичными данными между программами (или любой библиотекой для XML, JSON, если текстовые форматы приемлемы), 'sqlite' для облегченного решения базы данных? – jfs

ответ

2

Ну вот несколько советов, которые могут помочь:

  • при открытии файла, используйте ios_base :: двоичного флаг
  • убедитесь, что книга является POD (т.е. совместимого типа C)
  • убедитесь, что, когда вы читаете или пишете, что поток находится в допустимом состоянии до и после
  • не используют readBook.getId() == -1, чтобы проверить, если чтение удалось
  • убедитесь, что при вы ищете в потоке, вы не g в конце файла
  • используйте буфер, чтобы получить общее количество байтов в файле, а затем убедитесь, что вы не превысили его, прежде чем искать
  • всякий раз, когда вы ищете, выполните поиск относительно (используйте ios_base :: просить, например)
  • использования static_cast<char*>(static_cast<void*>(&book)) против reinterpret cast<char*>

Если у вас есть какие-то конкретные вопросы по поводу любого из этих предложений, сообщите нам об этом и, возможно, мы можем направлять вас лучше.

1

Вы, по-видимому чтение после конца файла. Ваш seekg звонок, вероятно, перемещает указатель чтения за конец, затем вы вызываете , читаете. Это приведет к отключению вашего потока. Проверьте это делает:

std::cout << dataFile.fail() << std::endl; 

после чтения вызова.

Тип управления записью, который вы пытаетесь сделать, не является тривиальной задачей. Возможно, вам стоит попробовать безсерверный DBE, например SQLite или другие библиотеки сериализации, такие как Boost.Serialization.

Кроме того, вы должны открыть файл с флагом ios :: binary.