C ++目录监视 - 如何检测副本已结束

时间:2012-02-07 18:52:59

标签: c++ windows visual-c++ directory

我有一个复制文件的文件夹。我想在将文件复制到目录后立即查看并处理文件。我可以检测文件何时在目录中,无论是通过轮询(我当前的实现)还是在某些测试中使用Windows API从我在网上找到的一些样本中找到。

问题是我检测到文件首次创建时仍然被复制。这使我的程序需要通过错误访问该文件(因为该文件尚未完成)。如何在复制开始时复制到复制结束时如何检测?我在Windows上使用C ++,所以答案可能取决于平台,但如果可能的话,我宁愿它与平台无关。

3 个答案:

答案 0 :(得分:4)

您可以使用锁定文件或特殊命名约定。最简单的是后者,可以这样工作:

假设您要移动名为“fileA.txt”的文件将其复制到目标目录时,请将其复制到“fileA.txt.partial”或类似名称。复制完成后,将文件从“fileA.txt.partial”重命名为“fileA.txt”。因此,就观看节目而言,“fileA.txt”的外观是原子的。

前面提到的另一个选项是锁定文件。因此,当您复制名为“fileA.txt”的文件时,首先要创建一个名为“fileA.txt.lock”的文件。复制完成后,您只需删除锁定文件。当观看节目看到“fileA.txt”时,它应该检查“fileA.txt.lock”是否存在,如果存在,它可以根据需要等待或重新访问该文件。

答案 1 :(得分:2)

你不应该投票。使用FindFirstChangeNotification(http://msdn.microsoft.com/en-us/library/windows/desktop/aa364417%28v=vs.85%29.aspx)查看目录以进行更改。

然后使用等待函数(http://msdn.microsoft.com/en-us/library/windows/desktop/ms687069%28v=vs.85%29.aspx)等待更改通知发生。< / p>

此处的概述和示例:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365261%28v=vs.85%29.aspx

我不确定文件写入完成的确切程度。 Evan Teran的回答是个好主意。

答案 2 :(得分:0)

您可以使用类似的东西,这已经过测试并且可以正常工作

bool IsFileDownloadComplete(const std::wstring& dir, const std::wstring& fileName) 
{
    std::wstring originalFileName = dir + fileName;
    std::wstring tempFileName = dir + L"temp";

    while(true)
    {
        int ret = rename(convertWstringToString(originalFileName).c_str(), convertWstringToString(tempFileName).c_str());
        if(ret == 0)
            break;      

        Sleep(10);
    }   

    /** File is not open. Rename to original. */
    int ret = rename(convertWstringToString(tempFileName).c_str(), convertWstringToString(originalFileName).c_str());
    if(ret != 0)
        throw std::exception("File rename failed"); 

    return true;
}