如何在生成文件後將文件移動到另一個文件夾而沒有名稱衝突問題?.Net:將文件從一個目錄移動到另一個目錄並避免名稱衝突
例如,我生成一個CSV文件名foo_20090820.csv,如果我再次在08/20/2009運行程序,那麼該文件將是foo_20090820.csv,因爲在我的目標文件夾中已經有一個文件生成第二個文件。該程序會遇到錯誤。
我試圖找到相同的文件名的目標文件夾,並在第二個文件前添加一些隨機數,但它不能很好地工作。
有什麼想法嗎?
如何在生成文件後將文件移動到另一個文件夾而沒有名稱衝突問題?.Net:將文件從一個目錄移動到另一個目錄並避免名稱衝突
例如,我生成一個CSV文件名foo_20090820.csv,如果我再次在08/20/2009運行程序,那麼該文件將是foo_20090820.csv,因爲在我的目標文件夾中已經有一個文件生成第二個文件。該程序會遇到錯誤。
我試圖找到相同的文件名的目標文件夾,並在第二個文件前添加一些隨機數,但它不能很好地工作。
有什麼想法嗎?
下面是我如何處理這個僞代碼:
newName = "foo_20090820.csv"
i = 1
while file exists newName
newName = "foo_20090820-" + i.ToString() + ".csv
i++
While Loop
Move oldFile to newName
另一個想法是編碼在文件名中的時間。我已經看到你有編碼的日期;我所建議的是時間。
所以你最終的東西是這樣的:
foo_yyyyMMdd_HHmmss(加的.csv當然)
這將增加小時(24小時時鐘格式),分鐘和秒,你的名字。
請注意,您不僅可以按照移動的順序對這些文件進行排序,但其文件名會告訴您何時移動了。
如果您完全不希望發生碰撞,您可以使用GUID。
這是對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
到文件名的解決方案。
雖然它仍然可以正常工作,但這段代碼會生成文件名,如foo1.csv,foo12.csv,foo123.csv。正如我所說,這將是功能性的,但如果能夠查看文件並根據寫入順序快速做出決定非常重要,則應該將原始基本名稱粘貼到var並附加到該文件。 – EBGreen 2009-08-24 15:05:12
我冒昧地進一步發展先前的解決方案。大多數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;
}
這是處理它的最好方法。唯一的另一種方式是,如果你只是想使用最新版本,那麼文件中存在一個名爲Exist的函數,它會告訴你文件是否存在,如果存在,你可以刪除舊文件。 – 2009-08-21 20:27:59
在你的例子中,你沒有遞增循環計數器。 – 2009-08-21 22:17:05
糟糕...我應該說僞代碼。我會修好它。謝謝。 – EBGreen 2009-08-21 23:46:29