views:

214

answers:

2

Hello,

I have a file that I want to read and write to a binary file using records. In the beginning I have an empty file and I want to add new record, but when I use the seekp function, then the location is at (-1) is it ok? Because when I check, I see that it hasnt written anything to the file. See code:

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++;
     }
    }

If anyone can tell me why I cant write anything to the file I will really appriciate it.

Thanks in advance,

Greg

+1  A: 

You are apparently reading past the end of the file. Your seekg call is probably moving the read pointer past the end, then you call read. This will set your stream into a fail state. Check this by doing:

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

after the read call.

The kind of record management you are trying to do isn't a trivial task. Maybe you should try a serverless DBE like SQLite or other serialization libraries like Boost.Serialization.

Also, you should open your file with the ios::binary flag as well.

Yuyo
+2  A: 

Well here are a few suggestions that may help:

  • when you open the file, use ios_base::binary flag
  • make sure that Book is a POD (i.e. a C compatible type)
  • make sure that when you read or write that the stream is in a valid state before and after
  • don't use readBook.getId() == -1 to check if the read succeeded
  • make sure that when you seek into the stream you're not going past the end of file
  • use the buffer to get the total number of bytes in the file and then ensure that you don't exceed it before seeking
  • whenever you seek, do a relative seek (use ios_base::beg for e.g)
  • use static_cast<char*>(static_cast<void*>(&book)) vs reinterpret cast<char*>

If you have any specific questions about any of those suggestions, let us know and perhaps we can guide you better.

Faisal Vali