【问题标题】:C# - File.Move - Could not find fileC# - File.Move - 找不到文件
【发布时间】:2022-08-14 19:06:38
【问题描述】:

File.Move 方法有一个奇怪的问题。 通常我有一个服务,它监视远程共享上出现的新文件,一旦他们这样做,它就会通过 \"ren\" cmd 函数更改其扩展名并调用其他服务。然后,此其他服务正在使用 File.Move 再次更改文件的扩展名。问题是有时第二个服务失败并从 System.IO.File.InternalMove 返回错误“找不到文件...”,而文件已经存在。

起初我以为可能是网络连接的问题,但我感觉它经常是由网络问题引起的。

接下来我开始深入研究 .net 源代码,发现了一些有趣的东西:

        if (!InternalExists(fullSourceFileName))
             __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName);
        
        if (!Win32Native.MoveFile(fullSourceFileName, fullDestFileName))
        {
            __Error.WinIOError();
        }

这是 File.InternalMove 方法的一部分,据我了解,该方法返回“找不到文件...”错误。简而言之,InternalExists 方法是通过检查 Marshal.GetLastWin32Error() 错误和稍后验证文件上的属性来检查文件是否存在。

另外奇怪的是,这种方法似乎使用了某种“hack”(不知道它是否与我的问题有关,但令人担忧):

   // For floppy drives, normally the OS will pop up a dialog saying
            // there is no disk in drive A:, please insert one.  We don\'t want that.
            // SetErrorMode will let us disable this, but we should set the error
            // mode back, since this may have wide-ranging effects.
            bool success = false;
            int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
            try {
                success = Win32Native.GetFileAttributesEx(path, GetFileExInfoStandard, ref data);
            }
            finally {
                Win32Native.SetErrorMode(oldMode);
            }

现在有趣的部分:) FileInfo 类还允许通过 MoveTo() 方法重命名文件。 在这种方法中,“移动”部分如下:

 if (!Win32Native.MoveFile(FullPath, fullDestFileName))
            __Error.WinIOError();

它与 File 类中的相同,但缺少“InternalExists”验证,所以乍一看它应该可以解决我的问题,但我有点担心这个缺失的检查。

有谁知道为什么它是这样实现的,如果我可以使用 FileInfo.MoveTo 方法? 另外,如果您对问题的原因有任何想法,请分享。目前我正在质疑,当第一个服务调用 \"ren\" cmd 程序时,新文件还没有完全重命名,这导致 File.Move 方法失败,但我必须验证它。

  • 我在尝试执行处理文件的程序时遇到了这样的问题。我发现不同的操作系统,主要是文件系统,对文件的处理方式不同。结果,该程序在我的 PC 和其他一些 PC 上运行,但不在其他 PC 上运行,主要是那些使用 Linux/ubuntu 操作系统的 PC。我没有解决方案,但给了你问题的线索。
  • 您的服务是否异步和并发运行?
  • 有点像,但是收到错误的服务应该一次处理一个文件。我检查了是否存在服务尝试同时处理同一文件两次的情况(例如,第一个更改扩展名,第二个由于文件实际上不再存在而出错)并且没有找到这种情况。同样对于我收到错误的每种情况,文件扩展名都没有改变。
  • 我猜它实际上是权限问题,InternalExists 返回的错误实际上不是ERROR_FILE_NOT_FOUND。因此,没有抛出正确的错误是一个错误。为什么需要存在检查尚不清楚:如果它不存在,无论如何您都会收到错误。

标签: c# file


【解决方案1】:

我猜这个错误实际上是一个权限问题,或者可能是一个锁定的文件,并且InternalExists 返回的错误实际上不是ERROR_FILE_NOT_FOUND,因为没有对其进行检查。

因此,没有抛出正确的错误是一个错误。

无论如何,为什么需要存在 Exists 检查尚不清楚:如果不存在,则在调用 MoveFile 时无论如何都会收到错误消息。

我建议您将此作为 GitHub 存储库上的错误提交。我认为它不太可能得到修复,但至少它会被记录在案。如果它以Won't fix 的身份关闭,您可能需要在文档中提交拉取请求,并注明这一点。

请注意,the current code 实际上是以下内容,它以稍微不同的方式实现相同的东西。

            if (!FileSystem.FileExists(fullSourceFileName))
            {
                throw new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, fullSourceFileName), fullSourceFileName);
            }

            FileSystem.MoveFile(fullSourceFileName, fullDestFileName, overwrite);

【讨论】:

    猜你喜欢
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多