如何使用Windows API检查文件是否仍在cpp中复制?

时间:2012-10-06 09:16:50

标签: c++ file winapi

在我目前的项目中,我们要求检查文件是否仍在复制。

我们已经开发了一个库,它会在特定文件夹上提供操作系统通知,例如file_added,file_removed,file_modified,file_renamed以及相应的文件路径。

这里的问题是,假设您添加1 GB文件,它会在复制文件时提供多个通知,例如file_added,file_modified,file_modified。

现在我决定通过检查文件是否正在复制来超越这些通知。基于此我将忽略事件。

我在c ++中写了下面的函数,它告诉文件是否被复制,它将文件路径作为输入。 详细信息: - 基本上它使用Windows API“CreateFile”来获取文件句柄。如果我们无法获得句柄,则确定正在复制文件。

问题: - 对于一些较大的文件,例如2 GB的.rar& .exe格式,这不起作用。能告诉我这是对的吗?如果不了解其他方法。

bool isFileBeingCopied(const boost::filesystem::path &filePath)
{
     //Log(INFO, "Checking if the given file is being copied or not for the file [%s]",filePath.string().c_str());
     HANDLE hFile = ::CreateFile(filePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
     DWORD dwLastError = GetLastError();

     if(hFile == NULL && hFile == INVALID_HANDLE_VALUE)
     {
          Log(INFO, "Gained invalid handle on the file - hence determining it, as being copied file [%s]",filePath.string().c_str());
          return true;
     }
     else
     {
          if(dwLastError == ERROR_SUCCESS )
          {
                CloseHandle(hFile);
                Log(INFO, "Able to gain the handle on the file - hence determining it, as copied file [%s]",filePath.string().c_str());
                return false;
          }
          else
          {
              Log(INFO, "Not able to gain the handle for the file - hence determining it, as being copied file [%s]",filePath.string().c_str());
              return true;
          }
     }               
}

3 个答案:

答案 0 :(得分:1)

除非您自己复制文件,否则无法从外部确定文件的复制状态。您可能必须使用计时器来检测文件修改事件何时停止发送给您。

答案 1 :(得分:1)

使用boost filesystem库,我们可以找出文件是否被复制。基本上boost :: filesystem :: fstream类打开I / O操作的文件。当文件当前被复制时,boost lib无法打开文件,is_open()方法将返回false。因此,在这种情况下,我们可以安全地假设该文件当前正在被复制。如果文件也被破坏或损坏,我们最终会遇到这种情况。

在所有其他情况下,is_open()返回true,我们可以考虑完成文件复制(在此用例中) 希望这段代码有所帮助。

boost::filesystem::fstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);

if(fileStream.is_open())
{
    //We could open the file, so file is good
    //So, file is not getting copied.
}
else
{
    //Wait, the file is currently getting copied. 
}

编辑:添加了更多解释

答案 2 :(得分:0)

如果文件先前已经打开(现在仍然是)dwShareMode = 0,IOW,在独占访问模式下,无论是否关闭,您都无法再次打开它文件正在复制(=写入)或不复制,因此不能依赖函数的返回值true

请注意,如果CreateFile()成功,请致电CloseHandle()并返回false。在此之后,文件可以立即打开以供另一个进程写入,并且,由于可能存在此竞争条件,因此无法再依赖返回的false值。如果你想阻止它,你不能关闭句柄,直到你不再有兴趣拥有该文件的独占访问权。

因此,这显然不是确定文件是否被复制(=写入)的正确方法。这似乎是一件毫无意义的事情。

在我看来,你正试图在这里解决错误的问题。在您的上下文中,您决定检查文件是否被复制(=写入)的真正问题是什么?如果你告诉我们,我们可以帮助解决这个真正的问题。