如何在没有名称冲突问题的情况下将文件生成到另一个文件夹后移动文件?
例如,我生成一个CSV文件名foo_20090820.csv,如果我稍后在08/20/2009再次运行该程序,那么该文件将是foo_20090820.csv,因为在我的目标文件夹上已经有一个文件在第二个之前生成文件。该程序将遇到错误。
我尝试查找目标文件夹中的相同文件名,并在第二个文件前添加一些随机数,但效果不佳。
任何想法?
答案 0 :(得分:4)
以下是我如何处理这个问题的伪代码:
newName = "foo_20090820.csv"
i = 1
while file exists newName
newName = "foo_20090820-" + i.ToString() + ".csv
i++
While Loop
Move oldFile to newName
答案 1 :(得分:2)
如果你绝对不想碰撞,你可以使用GUID。
答案 2 :(得分:1)
另一个想法是在文件名中对时间进行编码。我已经看到你有编码的日期;我所建议的是抓住时间。
所以你最终得到这样的东西:
foo_yyyyMMdd_HHmmss(当然加上.csv)
这会为你的名字增加几小时(24小时时钟格式),分钟和秒钟。
请注意,您不仅可以按照移动顺序对这些文件进行排序,而且他们的文件名会告诉您何时移动。
答案 3 :(得分:0)
这是对 EBGreen 解决方案的改进,它避免了在检查文件存在和创建文件之间的竞争条件。
bool SafeMove(string sourceFilename, string destFilename)
{
for (int i = 0; i < RetryThreshold; ++i)
{
try
{
File.Move(sourceFilename, destFilename);
return true;
}
catch(IOException)
{
destFilename =
Path.GetFilenameWithoutExtension(destFilename) + i.ToString() +
Path.GetExtension(destFilename);
}
}
return false;
}
此代码存在一些问题,但它表明在Move()
操作失败后尝试重试。您绝对应该执行一些更智能的异常处理,因为并非所有IOExceptions
都意味着重试的原因。此外,返回false
并不明智,因为我们丢失了错误上下文。
或者,如果您不关心目录或文件名的可读性,请使用 JP的解决方案将Guid
附加到文件名。
答案 4 :(得分:0)
我冒昧地将先前的解决方案进一步发展。大多数IOExceptions都需要由调用者处理。
private static string moveFileWithoutCollisions(string newDirectory, string filePath)
{
string fileName = Path.GetFileName(filePath);
string newFilePath = Path.Combine(newDirectory, fileName);
string bareFileName = Path.GetFileNameWithoutExtension(fileName);
string extension = Path.GetExtension(fileName);
while (true)
{
int suffix = 0;
while (File.Exists(newFilePath))
{
suffix++;
string fileNameWithSuffix = bareFileName + suffix + extension;
newFilePath = Path.Combine(newDirectory, fileNameWithSuffix);
}
try
{
File.Move(filePath, newFilePath);
}
catch (IOException)
{
if (File.Exists(newFilePath))
{
// Race condition: someone put a file there with the same name. Find a new name.
continue;
}
else
{
throw;
}
}
break;
}
return newFilePath;
}