1

レコードを使用してバイナリ ファイルを読み書きしたいファイルがあります。最初は空のファイルがあり、新しいレコードを追加したいのですが、シーク機能を使用すると、場所が (-1) になります。チェックすると、ファイルに何も書き込まれていないことがわかります。コードを参照してください:

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

ファイルに何も書き込めない理由を誰かが教えてくれれば、本当に感謝します。

前もって感謝します、

グレッグ

4

2 に答える 2

2

さて、ここに役立つかもしれないいくつかの提案があります:

  • ファイルを開くときは、ios_base::binary フラグを使用します
  • Book が POD (つまり、C 互換タイプ) であることを確認してください。
  • 読み取りまたは書き込みの前後で、ストリームが有効な状態であることを確認してください
  • 読み取りが成功したかどうかを確認するために readBook.getId() == -1 を使用しないでください
  • ストリームをシークするときに、ファイルの終わりを超えていないことを確認してください
  • バッファを使用してファイル内の合計バイト数を取得し、シークする前にそれを超えないようにします
  • シークするたびに、相対シークを行います (eg には ios_base::beg を使用します)
  • static_cast<char*>(static_cast<void*>(&book))対を使うreinterpret cast<char*>

これらの提案のいずれかについて具体的な質問がある場合は、お知らせください。

于 2009-06-14T18:02:32.253 に答える
1

ファイルの末尾を超えて読んでいるようです。あなたのseekg呼び出しは、おそらく読み取りポインターを最後まで移動しているので、 read を呼び出します。これにより、ストリームが失敗状態に設定されます。次のようにしてこれを確認します。

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

読み取り呼び出しの後。

あなたが行おうとしている種類の記録管理は、簡単な作業ではありません。おそらく、 SQLiteのようなサーバーレス DBEやBoost.Serializationのような他のシリアル化ライブラリを試す必要があります。

また、ios::binaryフラグも使用してファイルを開く必要があります。

于 2009-06-14T17:55:56.340 に答える