我需要在Windows中可靠地编写和重写文件(最好是原子地)。我目前正在创建该文件:
file_write
FILE.EXT.tmp
file_move
和FILE.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;
}
答案 0 :(得分:0)
通常的罪魁祸首是病毒扫描程序。他们在不可预测的时刻保存文件..
我会使用更渐进的退避 - 在第一次尝试时等待不到100毫秒,但在第5次尝试时等待更多。您可能希望在半秒后抛出一个消息框,告诉用户您正忙着。