2009-10-21 111 views
28

我已經看到了隨機命名的文件,包括使用C#:什麼是生成唯一文件名的最快方法?

System.IO.Path.GetRandomFileName() 

或使用

System.Guid 

和附加文件擴展名的若干建議。

我的問題是:什麼是生成唯一文件名的最快方法?

+37

爲什麼你不使用一種方法*速度夠快*? – Joren 2009-10-21 18:14:28

+1

一個很好的問題。答案是,我試圖從這個文件系統密集型應用程序中擠出每盎司的性能。 – 2009-10-21 18:17:17

+4

這真的取決於你的意思是「獨一無二」 - 它是否具有通用的獨特性,在文件系統中是獨一無二的,在同一個程序的不同線程中是唯一的......? – 2009-10-21 18:17:25

回答

36

GUID將非常快, ,因爲它的實施保證Windows可以在100納秒的時間範圍內生成至少16,384個GUIDS 。 (正如其他人指出的那樣,規範不能保證,只允許,但是,GUID的生成真的很快,真的)。在任何網絡上的任何文件系統上發生衝突的可能性非常低。這是很安全的,儘管最好的做法是始終檢查該文件名是否可用,實際上,您甚至不需要這樣做。

因此,您只查看除保存本身之外的任何I/O操作,並且在測試機器上測試0.2毫秒以生成名稱本身。相當快。

+2

哇!您是否有描述此實施保證的鏈接源? – 2009-10-21 18:19:27

+7

我不相信Windows gaurantees可以在100 nS中產生** 16,384個GUIDS - 只有通過GUID算法產生的值才能確保具有這種分佈級別。此外,使用邏輯,每100-Ns的16k GUIDS將達到每秒1630億GUIDS ...這意味着它只需要一個CPU週期的1/10來生成一個GUID?這沒有多大意義。 – LBushkin 2009-10-21 18:23:31

+0

看到關於GUID唯一性的這個問題http://stackoverflow.com/questions/39771/is-a-guid-unique-100-of-the-time – BlackTigerX 2009-10-21 18:24:13

3

如果您控制文件所在的目標位置,並且只有一個進程和線程寫入該文件,只需將一些自動遞增數字附加到基本名稱即可。

如果您不控制目標,或者需要多線程實現,請使用GUID。

+1

儘管我幾乎總是使用GUID來解決這個問題,但LBushkin對於性能是正確的。如果你真的想要*每一滴* perf,遞增一個整數並將其轉換爲一個字符串比生成一個Guid並將其轉換爲一個字符串更快......但是隻有當你擁有目錄的控制權時才能工作。 – 2009-10-21 19:02:21

17

你想System.IO.Path.GetTempFileName()

我不能說,其實無論是最快與否,但它是這樣做的正確方式,這是更重要的。

+0

+1 - 這是最簡單和最好的解決方案。 – Noldorin 2009-10-21 18:32:57

+31

這實際上創建一個文件。我認爲你的意思是System.IO.Path.GetRandomFileName() – 2009-10-21 18:46:41

+1

丹是正確的。它在Windows臨時目錄中創建一個文件。 – adrianbanks 2009-10-21 18:47:38

0

使用一個Int併爲每個文件增加它。

+2

OP想要一個唯一的文件名......那麼如果一個名爲(例如)'「1」'的文件已經存在? – Sree 2017-04-20 13:58:56

-1

類似:

file.MoveTo(deletedfilesdir + @"\" + f.Name + **DateTime.Now.ToFileTimeUtc()** + f.Extension); 
1

如果你控制的目錄,你可以基於該lastWriteTime命名文件:

DirectoryInfo info = new DirectoryInfo(directoryPath); 
long uniqueKey = info.LastWriteTime.Ticks+1L; 
string filename = String.Format("file{0}.txt", key); 

但是你要檢查這個代碼的表演:我想建設一個DirectoryInfo不是免費的。

+0

「建立一個DirectoryInfo不會免費」 - 我懷疑你是正確的,特別是如果驅動器/目錄不在計算機本地(網絡驅動器/ NAS/etc) – 2011-03-23 18:07:58

5

那麼我一直在寫文件系統驅動程序20年,並會說雷克斯是正確的。生成一個GUID要快得多,因爲它比尋找一個唯一的文件名要花費更少的開銷。 GetTempFileName實際上創建了一個文件,這意味着它必須調用整個文件系統驅動程序堆棧(誰知道將會有多少個調用並切換到內核模式。)GetRandomFileName聽起來更快,但我相信GUID調用甚至更快。人們沒有意識到的是,即使測試文件的存在,也需要通過驅動程序堆棧進行完整調用。它實際上導致打開,獲取屬性並關閉(至少3次調用,具體取決於級別)。實際上,它至少需要20次函數調用並轉換到內核模式。 GUIDS對獨特性的保證足以滿足大多數目的。

我的建議是生成名稱並僅在文件不存在時才創建文件。如果是,請拋出異常並捕獲它,然後生成一個新的GUID並重試。那樣,你沒有錯誤的機會,並且可以在夜晚輕鬆入睡。

在旁註中,檢查錯誤是如此的過頭。如果假設錯誤,代碼應該設計爲崩潰,或者捕獲異常並處理它。在異常堆棧上更快地推送和彈出地址,而不是每次檢查每個函數的錯誤。

0

我希望這種自我迭代功能可以幫助別人生成一個唯一的文件名。

public string getUniqueFileName(int i, string fullpath, string filename) 
{ 
    string lstDir = fullpath.Substring(0, fullpath.LastIndexOf('\\')); 
    string name = Path.GetFileName(fullpath); 
    string path = fullpath; 

    if (name != filename) 
     path = Path.Combine(lstDir, filename); 

    if (System.IO.File.Exists(path)) 
    { 
     string ext = Path.GetExtension(name); 
     name = Path.GetFileNameWithoutExtension(name);     
     i++; 
     filename = getUniqueFileName(i, fullpath, name + "_" + i + ext); 
    } 

    return filename; 
} 
+0

這不會創建名爲'file_1_2_3 '? – user5226582 2018-03-02 11:39:00

+0

雖然這會在路徑中生成一個唯一的文件名(雖然它不是線程安全的),但與其他方法相比,它會非常慢,只是簡單地生成一個唯一的文件名而不檢查它是否已經存在。我想這個操作需要快速生成一個唯一的文件名。 Btw你的答案解決了這個問題,它可能對別人有幫助。 – Perrier 2018-03-02 11:51:02

+0

是的,它的確如此。我的期望是增加相同的數字,但它變成了連接。需要修改代碼以使其按預期工作。如果有人更正我的代碼,會很感激。提前致謝。 – Bikuz 2018-03-02 11:52:08

相關問題