如果FileToDelete驻留在不同的驱动器中,则File.Replace抛出异常

时间:2014-02-07 10:14:03

标签: c# file-io replace

我不确定这是否是它抛出错误的原因。但对我来说,我在File.Replace执行驻留在不同目录中的文件的测试失败了。只是想知道其他人是否也是如此。

[TestMethod]
public void TestFileReplaceDifferentDirectory()
{
    string FileToReplace = @"c:\tools\file2.txt";
    string FileToDelete = @"D:\DropFolder\file0.txt";

    string strToWrite;
    using (var wtr = File.CreateText(FileToDelete))
    {
        long ticks = DateTime.Now.Ticks;
        strToWrite = string.Join(",", ticks, ticks, ticks);
        wtr.WriteLine(strToWrite);
        wtr.Flush();
        wtr.Close();
    }

    string BackupFileName = Path.Combine(
        Path.GetDirectoryName(FileToReplace),
        string.Format("{0}_{1}{2}",
            Path.GetFileNameWithoutExtension(FileToReplace),
            DateTime.Now.Ticks,
            Path.GetExtension(FileToReplace))
    );

    File.Replace(FileToDelete, FileToReplace, BackupFileName, false);

    using (StreamReader rdr = new StreamReader(FileToReplace))
    {
        string line = rdr.ReadLine();
        Assert.AreEqual(strToWrite, line);
    }
}


[TestMethod]
public void TestFileReplaceSameDirectory()
{
    string FileToReplace = @"c:\tools\file2.txt";
    string FileToDelete = @"c:\tools\file0.txt";

    string strToWrite;
    using (var wtr = File.CreateText(FileToDelete))
    {
        long ticks = DateTime.Now.Ticks;
        strToWrite = string.Join(",", ticks, ticks, ticks);
        wtr.WriteLine(strToWrite);
        wtr.Flush();
        wtr.Close();
    }

    string BackupFileName = Path.Combine(
        Path.GetDirectoryName(FileToReplace),
        string.Format("{0}_{1}{2}",
            Path.GetFileNameWithoutExtension(FileToReplace),
            DateTime.Now.Ticks,
            Path.GetExtension(FileToReplace))
    );

    File.Replace(FileToDelete, FileToReplace, BackupFileName, false);

    using (StreamReader rdr = new StreamReader(FileToReplace))
    {
        string line = rdr.ReadLine();
        Assert.AreEqual(strToWrite, line);
    }
}

我尝试写入临时文件(使用Path.GetTempFileName())并替换D:\DropFolder中的文件。它没有发生;它扔了一个System.IO.Exception

这是否意味着我唯一的选择是在与FileToReplace相同的目录中创建一种临时文件并执行此任务?

1 个答案:

答案 0 :(得分:1)

这是设计的。使用File.Replace()的目的是能够替换被另一个进程锁定的文件。非常重要的是,如果您只有一次保存珍贵数据,常见于机器关闭或意外程序终止。毋庸置疑,这确实需要一两招,因为Windows坚持要求您不要覆盖锁定的文件。

完全可以,因为操作系统只锁定文件 data ,但不锁定文件的目录条目。换句话说,即使它被锁定,重命名文件也是有效的。底层系统调用与File.Move()相同。

其中有两种不同的操作方式,具体取决于 destFileName 。如果目标路径位于同一驱动器上,则文件系统只需移动目录条目。非常快速且无故障。但是如果在同一个驱动器上,则无法工作,这也需要移动文件数据。在文件数据被锁定的情况下,这当然很慢并且根本不可能。

因此,传递给File.Replace()的 destinationBackupFileName 参数必须是与 sourceFileName 位于同一驱动器上的路径。移动失败时不执行此操作会导致异常。一般情况下不是很难做到,样板文件是使备份文件名与源文件名完全相同,例如,“.bak”附加到路径上。