2008-11-07 39 views
3

我有一個delphi(Win32)web應用程序,可以作爲CGI應用程序,ISAPI或Apache DLL運行。我希望能夠生成一個唯一的文件名前綴(對於給定時刻的所有當前請求都是唯一的),並且指出最好的方法是使用processID(處理CGI模式)以及threadID(處理DLL模式)。我可以根據ProcessID和ThreadID創建唯一的文件名嗎?

如何在Delphi中獲得唯一的進程ID和線程ID?

這些在多核/多處理器情況下(在單個網絡服務器計算機上)會是唯一的嗎?

編輯:請注意,我被告知反對這種做法,並因此接受的答案使用不同的方法來生成臨時文件名

回答

5

你有很多好主意在這裏介紹。

它是否也創建一個空文件來「鎖定」名稱?

no;我相信我們依靠Windows來確保從開機時起在同一臺計算機上永遠不會給出相同的臨時文件名兩次。

任何偶然的衝突,如果有產生的名稱和創建文件(如果我需要創建自己的文件)之間的分裂秒的延遲。

no;那會是一件非常糟糕的事情。

這是我用來獲取臨時文件的例程。

function GetTemporaryFileName:string; 
var 
    Path, FileName: array[0..MAX_PATH] of Char; 
begin 
    Win32Check(GetTempPath(MAX_PATH, Path) <> 0); 
    Win32Check(GetTempFileName(Path, '~EX', 0, FileName) <> 0); 
    Result:=String(Filename); 
end; 

你也可以使用從JclFileUtils.pas FileGetTempName()在JCL。

4

你能不能用一個GUID呢?

編輯:應該說第一次,檢查出以下兩個功能

CreateGuid 
GuidToString 
3

進程ID是不能保證在Windows上獨一無二的。它們對於這個過程的生命無疑是獨一無二的,但是一旦一個過程死掉了,它的ID就會立即被重用。我不確定ThreadIDs。如果這些是臨時文件,你可以使用與tmpfile或tmpnam等同的東西(C函數,但我認爲Delphi有相同的功能)。

由於傑米發佈了一個GUID可能會更好。

+0

「唯一在給定時刻當前所有的請求」 - 進程ID中重複使用就可以了,因爲這個文件只將存在於一個請求的生命中。但我想確定的是,在多核系統中,它們在特定時刻將是唯一的。並且,添加線程ID將佔多線程 – Graza 2008-11-07 17:18:27

+0

這意味着文件是臨時的(至少它似乎),在這種情況下,我只會使用tmpfile或其Delphic等效。 – grieve 2008-11-07 22:42:07

2

比這兩個選項中的任何一個都好,您應該使用系統功能_tempnam。它在目錄中爲不存在的文件返回一個隨機文件名。如果你願意,你可以給_tempnam提供一個前綴,這樣你創建的文件就可以識別你的文件了。如果你提供了一個獨特的前綴,不應該擔心有人打開你的文件。然而,還有另一種解決方案。

_tempnam只有當你想把文件放到一個任意的目錄時纔有用。如果您不在意目錄是系統臨時目錄,請改用tempfile_s。它也會爲你創建文件,所以不用擔心競爭條件......只有當你嘗試打開比系統可以處理更多的臨時文件時纔會發生錯誤。 tempfile_s的一個很大的缺點是,一旦你將它關閉,文件就會消失。

編輯:我得到了downvote,因爲這是一個C函數。您可以通過將它們導入delphi來訪問C運行時。看看msvcrt.dll here的一些例子。

function _tempnam(const Dir: PChar, const Prefix: PChar): PChar; cdecl; 
    external 'msvcrt.dll' name '_tempnam'; 
+0

它是否也創建一個空文件來「鎖定」名稱? - 也就是說,如果在生成名稱和創建文件(如果我需要自己創建文件)之間存在一秒的延遲時間,那麼是否存在*任何*碰撞的機會 – Graza 2008-11-07 17:22:19

+0

不知道默認情況下delphi是否可用。GetTempFileName的MSDN文檔確實提到了使用GUID – Jamie 2008-11-07 17:32:44

1

其他一切都給你一個良好的,合理的想法,但還是 - 如果您使用的是臨時存儲文件,如果這些文件將始終首先創建(這並不重要,如果有吃剩的文件在磁盤上已有相同的名稱,因爲無論如何你都會覆蓋它),那麼processid_threadid方法是完全有效的。

使用GetCurrentProcessIDGetCurrentThreadID Win32調用來訪問這兩個ID。

3

1)如何獲得一個唯一的進程ID &線程ID在德爾福:

答:
注:確保對「窗口」添加到您的使用條款中實現部分
注:紅雀是無符號的32位整數範圍從0到4294967295

implementation 
uses Windows; 

procedure MySolution(); 
var 
    myThreadID:Cardinal; 
    myProcessID:Cardinal; 
begin 
    myThreadID := windows.GetCurrentThreadID; 
    myProcessID := windows.GetCurrentProcessId; 
end; 

2)將這些處於多核/多處理器狀況(單個web服務器的機器上是唯一的)?
答:是的。

進程標識符是有效的從 直到 過程已經終止,並且是 整個系統獨特創建過程的時間。 (不 特有的處理器)

直到線程終止時, 線程標識符唯一地標識 線程整個系統中。 (同樣,全系統,不是唯一的 處理器)

5

Windows爲保證創建唯一的文件名提供的功能。無需創建自己:

這裏是圍繞功能德爾福包裝:

function CreateTempFileName(aPrefix: string): string; 
var 
    Buf: array[0..MAX_PATH] of Char; 
    Temp: array[0..MAX_PATH] of Char; 
begin 
    GetTempPath(MAX_PATH, Buf); 
    if GetTempFilename(Buf, PChar(aPrefix), 0, Temp) = 0 then 
    begin 
    raise Exception.CreateFmt(sWin32Error, [GetLastError, SysErrorMessage(GetLastError)]); 
    end; 
    Result := string(Temp); 
end; 
相關問題