如何知道文件复制成功?

18
静态方法File.Copy(String, String)没有返回值。如何在程序中判断该方法是否成功?如果没有抛出异常,那么File.Copy就执行成功了。但我想知道如何将“没有异常”作为一个条件来判断。
类似这样的:
if(no exception happened){

//my code goes here

}

编辑:我已经通过使用简单的计数器解决了这个问题,具体如下:

int i=0;
try{
    File.Copy();
}
catch(e1){
    i++;
}
catch(e2){
    i++;
}

if(i==0){
    //my code goes here
}

感谢所有的贡献者。我会仔细阅读你们的回答并选择最好的。


2
我的猜测是,如果它没有抛出异常(例如 IOException) - SynerCoder
你可以使用布尔值来实现它。 - Nasreddine
1
在处理文件系统时,你必须学会接受不确定性。当有人在 File.Copy() 返回且未抛出异常后绊倒电源线时,你仍然没有副本。不要为小事情烦恼,摆脱那些计数代码。 - Hans Passant
5个回答

24

如果操作没有抛出任何异常,这意味着操作成功。可能抛出的异常列表在这里

UnauthorizedAccessException

  • 调用者没有所需权限。

ArgumentException

  • sourceFileNamedestFileName是一个零长度字符串,仅包含空格,或包含一个或多个非法字符,如InvalidPathChars定义的那样。

  • -或-

  • sourceFileNamedestFileName指定目录。

ArgumentNullException

  • sourceFileName或destFileName为null。

PathTooLongException

  • 指定的路径、文件名或两者都超过系统定义的最大长度。例如,在基于Windows的平台上,路径必须少于248个字符,文件名必须少于260个字符。

DirectoryNotFoundException

  • sourceFileName或destFileName中指定的路径无效(例如,它位于未映射的驱动器上)。

FileNotFoundException

  • sourceFileName未找到。

IOException

  • destFileName已存在。

  • -或-

  • 发生了I/O错误。

NotSupportedException

  • sourceFileNamedestFileName格式无效。

1
虽然这并非必要,但您也可以使用 File.Exists 进行双重检查。 - Polynomial

12

错误

如果方法没有抛出异常,那么就没有错误发生。该方法能够执行它承诺要做的工作,因此它会离开并不会尝试返回某种状态码。你不需要检查状态码,因为你会知道它已经成功了。

如果方法失败了副本操作,则会抛出异常。在这种情况下,该方法无法执行其承诺要做的工作,这意味着发生了一些奇怪(异常)的事情,因此会抛出异常。由于抛出了异常,你必须处理它,否则你的程序会崩溃。所以检查状态码是没有意义的。你无法编写任何代码来读取那个状态码,因为状态检查代码永远不会被执行到。代码流将进入catch块或程序终止。

这些概念是使用异常处理错误的基础。

如何处理异常

除非你需要,并且有一种合理的方式来从异常中恢复,否则不要处理它们。让你的程序崩溃。这将使得在野外找到代码中的错误变得更加容易,因为未处理的异常将产生一个堆栈跟踪,告诉你程序哪个部分崩溃了,以及代码如何到达该点。

如果你有一种合理的恢复方式(例如简单地向用户显示错误消息并重试操作,或让他们输入不同的参数),则可以编写一个try/catch块。将可能抛出异常的代码编写在try块中,并在catch块中编写恢复代码。

try
{
    var file = File.Open(filename);
    // Todo: Work with open file here
}
catch(FileNotFoundException e)
{
    MessageBox.Show("Failed to open file - " + e.ToString());
    // Todo: Additional recovery here,
    // like telling the calling code to re-open the file selection dialog
}

请注意,您永远不应该捕获基本的Exception类型,而是应该捕获您可以处理的具体派生异常类型(例如FileNotFoundException)。这很有意义,因为您可能无法编写能够成功恢复OutOfMemoryException的代码,并且该异常可能会在您的代码的任何地方被抛出。如果您捕获Exception,那么您正在编写试图处理任何异常的代码,而不仅仅是您感兴趣的异常。

完成

File.Copy是同步操作。因此,一旦方法完成,实际的复制就已经完成了。

这意味着您可以在复制行后立即编写一行代码。该代码可以期望文件存在,完全复制并且可以访问。


谢谢,您的答案非常有用。SSamra 的回答给出了直接的解决方案。 - Aan
我有一个问题。File.Copy没有抛出任何异常,但它并没有复制文件。有什么想法吗? - rollsch

6

如果该方法没有抛出异常,则表示该方法已成功。


但我需要以编程方式完成它。有没有可能检查是否发生了异常? - Aan
@Adban,当然,如果抛出异常,有两种可能性:要么处理它(使用try/catch),要么让它传播,在这种情况下,您的程序将崩溃。 - Darin Dimitrov
4
你对C#和异常处理熟悉程度如何?如果你不确定如何判断是否出现异常,最好多看些书 - 不要仅仅试图通过这个“File.Copy”调用 - 要更全面地学习异常处理。 - Jon Skeet
@JonSkeet:我很擅长使用SEH,但我想知道如何将“无异常”作为条件。 - Aan
2
@Adban:嗯,你把方法调用放在了try/catch块中 - 如果没有触发catch块,它就没有抛出异常...(例如,在try块内的File.Copy调用之后只需加上return true;,并在catch块中加上return false;,如果你只需要一个返回是否成功的方法。) - Jon Skeet

2
如果没有异常,那就意味着文件已经成功地复制了...
using System;
using System.IO;

class Test 
{
    public static void Main() 
    {
        string path = @"c:\temp\MyTest.txt";
        string path2 = path + "temp";

        try 
        {
            // Create the file and clean up handles.
            using (FileStream fs = File.Create(path)) {}

            // Ensure that the target does not exist.
            File.Delete(path2);

            // Copy the file.
            File.Copy(path, path2);
            Console.WriteLine("{0} copied to {1}", path, path2);

            // Try to copy the same file again, which should succeed.
            File.Copy(path, path2, true);
            Console.WriteLine("The second Copy operation succeeded, which was expected.");
        } 

        catch 
        {
            Console.WriteLine("Double copy is not allowed, which was not expected.");
        }
    }
}

1

虽然我不知道你遇到了什么情况,但我有一个类似的情况,我需要复制文件并需要知道是否成功。由于在.NET API中找不到任何有用的东西,我的唯一选择是一直尝试,直到成功(尝试多次)。例如,在以下代码中,我必须在尝试5次后放弃。

private bool CopyDone()
{
  bool done = false;
  int i = 0;
  string source = "SourceFile";
  while (i < 5)
  {
    try
    {

      System.IO.File.Copy(source, target, true);
      i = 5;
      done = true;
    }
    catch (Exception exp)
    {
      Trace.WriteLine("File trouble " + exp.Message);
      System.Threading.Thread.Sleep(1000);
      i++;
    }

   }

  /* if(!done)
   {
      Trace.WriteLine("Failed to copy file "+source );
   }*/
  return done;

}

我认为这不是正确的方法,因此这不应该被接受作为答案。操作要么完成,要么未完成。你为什么认为第n次的结果比第一次的结果更好呢? - NoChance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接