fwrite后如何确保数据在磁盘上?

时间:2015-11-19 01:09:06

标签: c++ file synchronization fwrite

我有一个程序,其中一个线程写入文件,其他读取(同步)。但是从一段时间以来,写入和读取的值并不相等。实际上读者读取了正确数量的元素,但值不同。这可能是不将数据推送到磁盘的问题吗?虽然我在写完之后给fflush打电话,但我怎么能确定它是写的,所以我可以拒绝这个版本。 Os - 窗户。

FixedSizeQueue::FixedSizeQueue(const std::string& filename, size_t size)
    : size_(size)
    , head_(0)
    , tail_(0)
{
    fopen_s(&file_, filename.c_str(), "w+");
    InitializeCriticalSection(&critical_section_);
}

void
FixedSizeQueue::push_values(int* values, size_t count)
{
    Logger::report("Called push_values");
    EnterCriticalSection(&critical_section_);
    size_t free_items = (tail_ > head_) ? size_ - tail_ + head_ : size_ - head_ + tail_;
    if (count > free_items)
    {
        Logger::report("Buffer is full, can't push new values.");
        exit(1);
    }

    size_t till_end = (tail_ >= head_) ? size_ - tail_ : head_ - tail_;

    if (count < till_end)
    {
        fseek(file_, tail_ * sizeof(int), SEEK_SET);
        int g = fwrite(values, sizeof(int), count, file_);
        assert(g == count);

        tail_ += count;
    }
    else
    {
        fseek(file_, tail_ * sizeof(int), SEEK_SET);
        int h = fwrite(values, sizeof(int), till_end, file_);
        assert(h == till_end);
        fseek(file_, tail_ * sizeof(int), SEEK_SET);
        h = fwrite(values + count, sizeof(int), count - till_end, file_);
        assert(h == count - till_end);

        tail_ = count - till_end;
    }
    fflush(file_);
    LeaveCriticalSection(&critical_section_);
}

size_t
FixedSizeQueue::get_values(int* values)
{
    Logger::report("Called get_values");
    EnterCriticalSection(&critical_section_);
    const size_t item_count = (tail_ >= head_) ? tail_ - head_ : size_ - head_ + tail_;
    if (tail_ > head_)
    {
        fseek(file_, head_ * sizeof(int), SEEK_SET);
        fread(values, sizeof(int), item_count, file_);
    }
    else
    {
        fseek(file_, (size_ - head_) * sizeof(int), SEEK_SET);
        fread(values, sizeof(int), size_ - head_, file_);
        fseek(file_, 0, SEEK_SET);
        fread(values + size_ - head_, sizeof(int), tail_, file_);
    }

    head_ = tail_ = 0;

    LeaveCriticalSection(&critical_section_);

    return item_count;
}

感谢。

1 个答案:

答案 0 :(得分:0)

这篇归档的知识库文章为我们提供了帮助:https://jeffpar.github.io/kbarchive/kb/066/Q66052/

最初使用fopen_s打开文件时,我们将“ c”模式选项作为最后一个选项:

fopen_s( path, "wc") // w - write mode, c - allow immediate commit to disk

请参见https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-s-wfopen-s?view=vs-2019

然后,因为它是Windows,所以当您要强制刷新到磁盘时,请调用

_flushall()

我们在致电

之前先打了这个电话
fclose()

我们遇到了您所描述的确切问题,并且此方法已将其解决。

摘自上述知识库文章:

“ Microsoft C / C ++ 7.0版为fopen()引入了” c“模式选项 功能。当应用程序打开文件并指定“ c”模式时, 当运行库将文件缓冲区的内容写入磁盘时, 应用程序调用fflush()或_flushall()函数。 “