1

我有一个文件,我想使用记录读取和写入二进制文件。一开始我有一个空文件,我想添加新记录,但是当我使用 seekp 功能时,位置在(-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 来检查读取是否成功
  • 确保当您搜索流时不会超过文件末尾
  • 使用缓冲区获取文件中的总字节数,然后确保在查找之前不超过它
  • 每当您寻找时,请进行相对寻找(例如,使用 ios_base::beg)
  • 使用static_cast<char*>(static_cast<void*>(&book))vsreinterpret 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 回答