2009-06-14 8 views
1

J'ai un fichier que je veux lire et écrire dans un fichier binaire en utilisant des enregistrements. Au début, j'ai un fichier vide et je veux ajouter un nouvel enregistrement, mais quand j'utilise la fonction seekp, alors l'emplacement est à (-1) est-ce correct? Parce que quand je vérifie, je vois qu'il n'a rien écrit dans le fichier. Voir le code:Travailler avec des fichiers fstream dans un chaînage de débordement en 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++; 
     } 
    } 

Si quelqu'un peut me dire pourquoi je ne peux rien écrire dans le fichier, je l'apprendrai vraiment.

Merci à l'avance,

Greg

+0

:(Personne ne sait comment le résoudre? –

+0

si ce n'est pas un devoir alors pourquoi ne pas utiliser des solutions existantes par exemple, 'Boost.Serialization' si vous avez besoin sérialisation,' Google Protocole Buffers' pour échanger des données binaires entre les programmes (ou toute bibliothèque pour XML, JSON si les formats de texte sont acceptables), 'sqlite' pour une solution de base de données légère? – jfs

Répondre

2

Eh bien voici quelques suggestions qui pourraient vous aider:

  • lorsque vous ouvrez le fichier, utilisez ios_base :: drapeau binaire
  • assurez-vous que livre est un POD (par exemple un type compatible C)
  • assurez-vous que lorsque vous lisez ou écrivez que le flux est dans un état valide avant et après
  • ne pas utiliser readBook.getId() == -1 pour vérifier si la lecture a réussi
  • assurez-vous que lorsque vous cherchez dans le flux que vous n'êtes pas g oing passé la fin du fichier
  • utilisez le tampon pour obtenir le nombre total d'octets dans le fichier, puis assurez-vous de ne pas le dépasser avant de rechercher
  • chaque fois que vous cherchez, faites une recherche relative (utilisez ios_base :: mendier par exemple)
  • utilisation static_cast<char*>(static_cast<void*>(&book)) vs reinterpret cast<char*>

Si vous avez des questions au sujet de l'une de ces suggestions, faites-nous savoir et peut-être que nous pouvons vous guider mieux.

1

Vous lisez apparemment passé la fin du fichier. Votre appel seekg est probablement déplacer le pointeur de lecture après la fin, puis vous appelez lire. Cela va définir votre flux dans un état d'échec. Vérifiez ceci en faisant:

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

après la lecture appel.

Le type de gestion des enregistrements que vous essayez de faire n'est pas une tâche triviale. Peut-être que vous devriez essayer un DBE sans serveur comme SQLite ou d'autres bibliothèques de sérialisation comme Boost.Serialization.

En outre, vous devez également ouvrir votre fichier avec le drapeau ios :: binary.