C# File.Move不起作用-文件已存在

C# File.Move不起作用-文件已存在,c#,file-io,C#,File Io,我有一个文件夹: c:\测试 我正在尝试以下代码: File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test"); 我得到一个例外: 文件已存在 输出目录肯定存在,输入文件也在那里。根据这一点,没有“存在时覆盖”参数。您试图指定目标文件夹,但必须给出完整的文件规范 再次阅读文档(“提供指定新文件名的选项”),我认为在目标文件夹规范中添加反斜杠可能会起作用。您需要将其移动到另一个文件(而不是文件夹),这也可以用于重命名 移动: 重命名: File.Mov

我有一个文件夹:

c:\测试

我正在尝试以下代码:

File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test");
我得到一个例外:

文件已存在

输出目录肯定存在,输入文件也在那里。

根据这一点,没有“存在时覆盖”参数。您试图指定目标文件夹,但必须给出完整的文件规范


再次阅读文档(“提供指定新文件名的选项”),我认为在目标文件夹规范中添加反斜杠可能会起作用。

您需要将其移动到另一个文件(而不是文件夹),这也可以用于重命名

移动:

重命名:

File.Move(@"c:\test\SomeFile.txt", @"c:\test\SomeFile2.txt");
在您的示例中,它之所以说“文件已经存在”,是因为
C:\test\test
试图创建一个没有扩展名的文件
test
,但无法创建,因为已经存在同名文件夹。

您需要的是:

if (!File.Exists(@"c:\test\Test\SomeFile.txt")) {
    File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");
}

这将:

  • 如果目标位置不存在该文件,请成功移动该文件,或
  • 如果目标位置确实存在该文件,请将其删除,然后移动该文件
编辑:我应该澄清我的答案,即使它是最上等的! File.Move的第二个参数应该是目标文件,而不是文件夹。您正在将第二个参数指定为目标文件夹,而不是目标文件名,这正是File.Move所需要的。
因此,您的第二个参数应该是
c:\test\test\SomeFile.txt

如果文件确实存在并且您想替换它,请使用以下代码:

string file = "c:\test\SomeFile.txt"
string moveTo = "c:\test\test\SomeFile.txt"

if (File.Exists(moveTo))
{
    File.Delete(moveTo);
}

File.Move(file, moveTo);
您可以对
标志执行p/Invoke-pass 11(
移动文件\u复制\u允许|移动文件\u替换\u现有|移动文件\u写入|

或者,你可以直接打电话

Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);

添加Microsoft.VisualBasic作为参考后。

我个人更喜欢这种方法。 这将覆盖目标上的文件,删除源文件,并防止在复制失败时删除源文件

string source = @"c:\test\SomeFile.txt";
string destination = @"c:\test\test\SomeFile.txt";

try
{
    File.Copy(source, destination, true);
    File.Delete(source);
}
catch
{
    //some error handling
}

请尝试
Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(源、目标、真)
。最后一个参数是Overwrite switch,它是
System.IO.File.Move
没有的。

如果您没有选项删除新位置中已经存在的文件,但仍然需要从原始位置移动和删除,此重命名技巧可能会起作用:

string newFileLocation = @"c:\test\Test\SomeFile.txt";

while (File.Exists(newFileLocation)) {
    newFileLocation = newFileLocation.Split('.')[0] + "_copy." + newFileLocation.Split('.')[1];
}
File.Move(@"c:\test\SomeFile.txt", newFileLocation);
这假定文件名中唯一的“.”在扩展名之前。 它在扩展名之前将文件一分为二,在中间附加“\u copy.”。 这允许您移动文件,但如果文件已经存在,或者副本的副本已经存在,或者副本的副本存在,则会创建副本…;)

1)对于.Net Core 3.0及更高版本的C#,现在有了第三个布尔参数:


2) 对于所有其他版本的.Net来说,这是最好的答案。复制并覆盖,然后删除源文件。这是更好的,因为它使它成为一个原子操作。(我试图用此更新MS文档)

如果输入文件已在输出目录中,则该文件已存在,从而解释了异常。您需要指出您希望原始文件被新文件覆盖。听起来错误正好告诉您出了什么问题。@Josh否。听起来Windows有非POSIX文件系统行为,这使得不可能找到一个简单的可移植事务性文件更新模式/例程。@binki-POSIX与此无关(你指的是原子操作吗?),NTFS确实支持真正的事务性操作,如回滚和获取原始文件内容。正如其他人回答的那样,Win32确实允许使用replace.I'ts.NET的file.move进行移动,但不提供该功能。您可以使用replace进行移动,也可以使用类似的库进行事务性操作AlphaFS@binki无论如何,我的行为它在不同的文件系统上定义得很好,不管论坛讨论怎么说。file.Move不调用Ex或Transact方法的原因是FAT不是原子的,行为也不一样。重命名不是元数据操作,需要实际的数据移动。忘记tr吧AnActions&写时复制。这不是一个很好的决定,他当然不需要检查文件是否不在那里,因为他正在检查,而文件不在那里。当尝试将文件移动到另一个文件夹时,由于没有将文件名追加到目标文件夹中而导致异常。如果你的应用程序是多线程的(或者有其他进程正在处理您的文件)即使使用“if(Exists)Delete”代码,您也可能会得到相同的异常。由于还有一段时间,其他线程/进程可能会在删除后将文件放回,因此您执行移动,然后无论如何都会得到异常。值得记住:-)这个答案对谷歌试图覆盖现有文件后的大多数人仍然有效。大多数处于这种困境的人没有像OP.@v.oddou这样的语法/类型-o问题。有趣的是,如果文件不存在,file.Delete确实可以正常工作,并且什么也不做。如果路径中的任何目录不存在,则您可以删除但获取DirectoryNotFoundException。@JirkaHanika您可以将if(File.Exists)更改为while(File.Exists)。这对于小文件很好(不需要原子移动),但是对于大文件,或者需要确保不会出现重复的情况,这是有问题的。为什么您更喜欢
File.Copy,File.Delete
而不是
File.Move
?File.Move没有覆盖选项。这取决于您的使用情况,可能会导致问题。“Move”是文件系统监视程序中的真实事件。文件系统事件列表中的某些内容将获得删除和创建事件,而不是移动事件。这也将更改底层文件系统ID。对于大型文件,这不是性能要低很多吗?如果源和目标
Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);
string source = @"c:\test\SomeFile.txt";
string destination = @"c:\test\test\SomeFile.txt";

try
{
    File.Copy(source, destination, true);
    File.Delete(source);
}
catch
{
    //some error handling
}
string newFileLocation = @"c:\test\Test\SomeFile.txt";

while (File.Exists(newFileLocation)) {
    newFileLocation = newFileLocation.Split('.')[0] + "_copy." + newFileLocation.Split('.')[1];
}
File.Move(@"c:\test\SomeFile.txt", newFileLocation);
In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.