可靠地在Windows中编写和移动文件

时间:2014-05-09 05:13:22

标签: c++ windows file-io

我需要在Windows中可靠地编写和重写文件(最好是原子地)。我目前正在创建该文件:

  • 在内存中构建文件内容
  • 使用file_write
  • 致电FILE.EXT.tmp
  • 使用file_moveFILE.EXT
  • 致电FILE.EXT.tmp

这通常有效;但偶尔会file_move返回5 Access is denied。我不知道为什么会这样,但我需要能够处理它。

目前我正在解决这个问题,通过在循环中调用我的函数进行5次迭代,如果写入失败则在写入之间延迟100ms。这似乎有效,但我想知道是否有更好的方法。

typedef long WIN32_ERROR;

WIN32_ERROR file_move(std::string const &dest, std::string const &src)
{
    if (MoveFileEx( src.c_str(), dest.c_str(), MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH ))
        return 0;

    long err = GetLastError();
    if (err != ERROR_CALL_NOT_IMPLEMENTED && err != ERROR_NOT_SAME_DEVICE)
        return err;

    if (!CopyFile(src.c_str(), dest.c_str(), 0))
        return GetLastError();

    DeleteFile(src.c_str());
    return 0;
}

WIN32_ERROR file_write( std::string const &dest, void const *data, size_t data_len )
{
    HANDLE h = CreateFile( dest.c_str(), GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS,
        FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_FLAG_SEQUENTIAL_SCAN |
        FILE_FLAG_WRITE_THROUGH,
        NULL );

    if ( h == INVALID_HANDLE_VALUE )
        return GetLastError();

    unsigned long n_written;
    if ( !WriteFile(h, data, data_len, &n_written, NULL) )
        return CloseHandle(h), GetLastError();

    if ( n_written != data_len )
    {
        CloseHandle(h);
        throw std::runtime_error("Write length error on file " + dest);
    }

    FlushFileBuffers(h);
    CloseHandle(h);

    return 0;
}

1 个答案:

答案 0 :(得分:0)

通常的罪魁祸首是病毒扫描程序。他们在不可预测的时刻保存文件..

我会使用更渐进的退避 - 在第一次尝试时等待不到100毫秒,但在第5次尝试时等待更多。您可能希望在半秒后抛出一个消息框,告诉用户您正忙着。