等到文件完全写入

lev*_*evi 66 c# filesystems io copy file

在一个目录中创建文件(FileSystemWatcher_Created)时,我将其复制到另一个目录中.但是当我创建一个大(> 10MB)文件时,它无法复制文件,因为它已经开始复制,当文件尚未完成创建时...
这导致无法复制文件,因为它被另一个进程使用提高.;(
任何帮助?

class Program
{
    static void Main(string[] args)
    {
        string path = @"D:\levan\FolderListenerTest\ListenedFolder";
        FileSystemWatcher listener; 
        listener = new FileSystemWatcher(path);
        listener.Created += new FileSystemEventHandler(listener_Created);
        listener.EnableRaisingEvents = true;

        while (Console.ReadLine() != "exit") ;
    }

    public static void listener_Created(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine
                (
                    "File Created:\n"
                   + "ChangeType: " + e.ChangeType
                   + "\nName: " + e.Name
                   + "\nFullPath: " + e.FullPath
                );
        File.Copy(e.FullPath, @"D:\levan\FolderListenerTest\CopiedFilesFolder\" + e.Name);
        Console.Read();
    }
}
Run Code Online (Sandbox Code Playgroud)

Rom*_*ain 41

您面临的问题只有解决方法.

在开始复制过程之前检查文件是否正在进行中.您可以调用以下函数,直到获得False值.

第一种方法,直接从这个答案复制:

private bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;

    try
    {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
        //the file is unavailable because it is:
        //still being written to
        //or being processed by another thread
        //or does not exist (has already been processed)
        return true;
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }

    //file is not locked
    return false;
}
Run Code Online (Sandbox Code Playgroud)

第二种方法:

const int ERROR_SHARING_VIOLATION = 32;
const int ERROR_LOCK_VIOLATION = 33;
private bool IsFileLocked(string file)
{
    //check that problem is not in destination file
    if (File.Exists(file) == true)
    {
        FileStream stream = null;
        try
        {
            stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
        }
        catch (Exception ex2)
        {
            //_log.WriteLog(ex2, "Error in checking whether file is locked " + file);
            int errorCode = Marshal.GetHRForException(ex2) & ((1 << 16) - 1);
            if ((ex2 is IOException) && (errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION))
            {
                return true;
            }
        }
        finally
        {
            if (stream != null)
                stream.Close();
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • 而你忘了复制常量值(`ERROR_SHARING_VIOLATION` = 32,`ERROR_LOCK_VIOLATION` = 33) (2认同)

Ste*_*tty 11

从以下文档FileSystemWatcher:

OnCreated创建文件后立即引发该事件.如果正在将文件复制或传输到监视目录中,OnCreated则会立即引发该 事件,然后是一个或多个 OnChanged事件.

因此,如果复制失败,(捕获异常),将其添加到仍需要移动的文件列表中,并在OnChanged事件期间尝试复制.最终,它应该工作.

像(不完整;捕获特定异常,初始化变量等):

    public static void listener_Created(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine
                (
                    "File Created:\n"
                   + "ChangeType: " + e.ChangeType
                   + "\nName: " + e.Name
                   + "\nFullPath: " + e.FullPath
                );
        try {
            File.Copy(e.FullPath, @"D:\levani\FolderListenerTest\CopiedFilesFolder\" + e.Name);
        }
        catch {
            _waitingForClose.Add(e.FullPath);
        }
        Console.Read();
    }

    public static void listener_Changed(object sender, FileSystemEventArgs e)
    {
         if (_waitingForClose.Contains(e.FullPath))
         {
              try {
                  File.Copy(...);
                  _waitingForClose.Remove(e.FullPath);
              }
              catch {}
         }
   }
Run Code Online (Sandbox Code Playgroud)


Joh*_*mes 10

这是一个旧线程,但我会为其他人添加一些信息.

我在编写PDF文件的程序时遇到了类似的问题,有时它们需要30秒才能渲染..这与我的watcher_FileCreated类在复制文件之前等待的时间相同.

文件未锁定.

在这种情况下,我检查了PDF的大小,然后在比较新大小之前等待了2秒,如果它们不相等,则线程将睡眠30秒并再次尝试.


zmb*_*mbq 5

您实际上很幸运-编写文件的程序将其锁定,因此您无法打开它。如果它没有锁定它,那么您将复制一个部分文件,而不会有任何问题。

当您无法访问文件时,可以假定它仍在使用中(更好-尝试以独占模式打开它,并查看是否有人正在打开它,而不是从File.Copy的失败中猜测出来)。如果文件已锁定,则必须在其他时间复制它。如果未锁定,则可以将其复制(此处可能存在竞争状况)。

什么时候是“其他时间”?当FileSystemWatcher在每个文件中发送多个事件时,我不记得-检查一下,您只需忽略该事件并等待另一个事件就足够了。如果没有,您可以随时设置时间并在5秒钟内重新检查文件。