我正在将文件从一个位置复制到另一个位置。我遇到了一个问题,有时一个同名的文件会尝试保存,这会破坏程序。所以我添加了下面的逻辑,在复制之前在文件名中添加一个数字:
int counter = 0;
try
{
File.Copy(FileToCopy, FileToSave);
}
catch (Exception)
{
string CurrentFileName = FileToSave.Split('\\', '\\')[4];
string CurretFilePrefix = CurrentFileName.Split('.')[0];
string CurrentFileSuffix = CurrentFileName.Split('.')[1];
string UpdatedFileName = CurretFilePrefix + "_" + counter + "." + CurrentFileSuffix;
File.Copy(FileToCopy, UpdatedFileName);
counter++;
}
但是,这现在导致崩溃,说文件已经存在:
当我检查文件不存在时:
为什么我会收到此异常?如何保存这些文件的副本?
答案 0 :(得分:2)
解决这个问题的好方法包括(i)循环; (ii)使用Path
表达; (iii)当您可以测试文件是否存在时,避免使用try-catch
; (iv)对两个线程或进程试图同时执行同一副本并且每个都超过File.Exists
检查的极不可能的情况使用特定的异常; (v)避免while-true-forever循环,因为即使最好的代码也可能包含错误,这些错误可能导致服务器上的生产代码中的自旋等待,并且最好有一个异常,告诉你什么时候出了问题。
int counter = 0;
string proposedDest = dest;
while(counter < 5000)
{
if (!File.Exists(proposedDest))
{
try
{
File.Copy(fileToCopy, proposedDest);
break;
}
catch (IOException ex) when ((uint)ex.HResult == 0x80070050)
{
}
}
counter++;
proposedDest = Path.Combine(Path.GetDirectoryName(dest),
Path.GetFileNameWithoutExtension(dest) +
"_" + counter + Path.GetExtension(dest));
}
;
if (counter == 5000)
throw new Exception($"Could not copy file {fileToCopy} too many retries");
[更好的方法也不会使用通过代码散布的硬编码常量;)]
答案 1 :(得分:1)
由于CurrentFileName
是相对的,因此您尝试将文件保存在可执行文件的位置。如果您的文件存在,请检查该目录。
此外,还有更好的方法可以查找文件是否存在,还可以获取给定文件的文件名和扩展名。
即。您应该使用File.Exists
方法来确定文件是否存在,而不是使用流控制的异常
if (File.Exists(FileToSave))
{
FileToSave = GetNewFileName(FileToSave)
}
try
{
File.Copy(FileToCopy, FileToSave);
}
catch (Exception)
{
//something went really wrong
}
您还应该使用Path
方法获取名称的一部分,而不是“知道”获取文件名的第五部分(Path.GetExtension
,Path.GetFileNameWithoutExtension
)
private string GetNewFileName(string oldFileName){
var counter = 0;
var extension = Path.GetExtension(oldFileName);
var directory = Path.GetDirectoryName(oldFileName);
var fileName = Path.GetFileNameWithoutExtension(oldFileName);
var newFileName = Path.Combine(directory,
string.Format("{1}_{2}{3}", filename, counter, extension);
while (File.Exists(newFileName)){
counter++;
newFileName = Path.Combine(directory,
string.Format("{1}_{2}{3}", filename, counter, extension);
}
return newFileName;
}
答案 2 :(得分:0)
改为使用:
string CurrentFileName = System.IO.Path.GetFileName(FileToSave);
string CurretFilePrefix = System.IO.Path.GetFileNameWithoutExtension(FileToSave);
string CurrentFileSuffix = System.IO.Path.GetExtension(FileToSave);
string UpdatedFileName = CurretFilePrefix + "_" + counter + "." + CurrentFileSuffix;
然后你有
File.Copy(FileToCopy, UpdatedFileName);
你确定这不应该
File.Copy(FileToSave, UpdatedFileName); // FileToSave instead of FileToCopy