2010-03-23 59 views
2

HI使用Delphi在目錄中查找最舊文件的最快方法

我們有大量將視頻捕獲到磁盤驅動器的遠程計算機。每臺攝像機都有自己獨特的目錄,任何一個磁盤上最多可以有16個目錄。

我試圖找到磁盤上最老的視頻文件,但使用FindFirst/FindNext比較文件創建日期時間需要永遠。

有沒有人知道更有效的方法找到目錄中最舊的文件?我們從中央HO位置遠程連接到PC。

的問候,彼得

- 更新

謝謝大家的答案。最後我使用了以下內容。

  1. 將驅動器映射( 'W:')使用windows.WNetAddConnection2
    //使用在遠程計算機上執行目錄的遠程計算機的cmd.exe/C DIR
    //注意:驅動器字母是相對於遠程計算機。 (psexec -w參數)
  2. psexec \\<IPAddress> -i /accepteula -w "c:\windows\system32" cmd.exe "/c dir q:\video /OD /TC /B > q:\dir.txt"
  3. //讀取「w:\ dir.txt」的第一行以獲取該目錄中最舊的文件。
  4. //斷開使用
+0

你可以添加一些東西到過程中,以便找到文件不涉及迭代磁盤上的文件?另外,你是在機器上運行程序還是通過網絡運行?如果是後者,我建議你嘗試在機器上運行程序,這樣文件夾迭代不會在網絡上運行。 –

+0

我不知道如何將它變成答案,但是如果您可以在遠程計算機上安裝軟件,我想知道是否可以使用Power Shell版本2中的遠程功能。可以在遠程計算機上運行Power Shell腳本以查找最舊的文件,並且您將在本地獲取文件信息。我不確定你會如何得到答案,但我相信這是可能的。 –

回答

0

首先在遠程計算機,搶how to run a DOS program and pipe its output to a TStrings從該頁面RunDosAppPipedToTStrings程序。該示例使用TMemo的Lines屬性,但可以傳入TStringList等任何TString。請注意,如果CreateProcess返回false,這將失敗。您可能需要將其他大小寫添加到引發異常的「if CreateProcess」塊中。

然後在與EXE相同的文件夾中創建一個簡單的批處理文件。稱它爲getdir.bat。所有這應該說是:

dir %1

這將產生傳遞到它的任何文件夾的目錄列表。不幸的是,「dir」是DOS關鍵字命令,而不是程序,所以你不能直接調用它。用批處理文件包裝它可以解決這個問題。這是一個黑客,但它的工作原理。如果你能找到更好的方式來運行DIR,那麼更好。

你要調用RunDosAppPipedToTStrings的代碼看起來是這樣的:

procedure GetDirListing(dirname: string; list: TStringList); 
const 
    CMDNAME = '%s\getdir.bat "%s"'; 
var 
    path: string; 
begin 
    list.Clear; 
    path := ExcludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))); 
    RunDosAppPipedToTStrings(format(CMDNAME, [path, dirname]), list, false); 
end; 

然後所有剩下要做的就是解析輸出,提取日期,時間和文件名,按日期排序和時間,並獲取具有最低日期的文件的文件名。我會留給你很多。

+0

爲什麼這是比FindFirst/FindNext更好的解決方案? –

+0

由於FindFirst/FindNext是一種迭代解決方案,可以爲每個文件始終返回網絡驅動器。在本地機器上這樣做很好,但是當你在網絡上出現重大延遲時,你想要一步獲得所有信息,只需要等待一次,然後將其排序到客戶端。 –

+0

所以你是說DIR有其他方法來查找網絡驅動器的內容? –

0

如果您可以在遠程計算機上運行可以迭代目錄的東西,那將是最快的方法。如果您想使用Mason的示例,請嘗試使用SysInternals中的PsExec啓動它。

如果你只能在本地運行一個應用程序,那麼沒有比FindFirst/FindNext更快的方法,而且你最終做的任何事情都可以歸結爲此。如果您的本地計算機正在運行Windows 7,則可以使用FindFirstFileEx代替,該代碼具有標誌以指示它應該使用較大的緩衝區進行傳輸,並且不應讀取8.3別名,這可以幫助提高速度。

+0

噢,是的,有一個更快的解決方案:查詢Windows搜索索引,可以遠程完成。但是,如果Windows搜索沒有激活,我同意你的意見...... – Leo

+0

如果你發佈了一個答案,說明如何做到這一點,你有我的投票。 –

1

您也可以嘗試FindFirstFileExFindExInfoBasic參數,並在Windows 7或Server 2008 R2或更高版本,FIND_FIRST_EX_LARGE_FETCH其中should improve performance

0

我在開發的傳真服務器軟件上遇到了幾乎相同的問題。我必須按照從成千上萬的收到的順序發送傳真(全部存儲在目錄中)。我採取的解決方案(這是緩慢的開始,但運行速度快)是使用

SearchRec.Time 

爲重點,以使所有文件的排序列表。該文件是在列表中後,我設置文件屬性爲faSysFile:

NewAttributes := Attributes or faSysFile; 

現在,當我做了新的搜索與

FileAttrs := (faAnyFile and not faDirectory); 

唯一不屬於文件faSysFile會顯示出來,所以我可以在列表中添加新的文件。 現在你有一個列表,所有的文件按時間排序。 不要忘記,當您啓動應用程序時,第一步是從文件夾中的文件中移除faSysFile屬性,以便可以再次處理它們。

procedure FileSetSysAttr(AFileName: string); 
var 
    Attributes, NewAttributes: Word; 
begin 
    Attributes := FileGetAttr(AFileName); 
    NewAttributes := Attributes or faSysFile; 
    FileSetAttr(AFileName, NewAttributes); 
end; 

procedure FileUnSetSysAttr(AFileName: string); 
var 
    Attributes, NewAttributes: Word; 
begin 
    Attributes := FileGetAttr(AFileName); 
    NewAttributes := Attributes and not faSysFile; 
    FileSetAttr(AFileName, NewAttributes); 
end; 

procedure PathUnSetSysAttr(APathName: string); 
var 
    sr: TSearchRec; 
    FileAttrs: Integer; 
begin 
    FileAttrs := (faAnyFile and not faDirectory) and (faAnyFile or faSysFile); 
    APathName := IncludeTrailingBackslash(APathName); 
    if SysUtils.FindFirst(APathName + '*.*', FileAttrs, sr) = 0 then 
    try 
    repeat 
     if (sr.Attr and faDirectory) = 0 then 
     FileUnSetSysAttr(APathName + sr.Name); 
    until SysUtils.FindNext(sr) <> 0; 
    finally 
    SysUtils.FindClose(sr); 
    end; 
end; 

我知道這不是最好的解決方案,但適用於我。

相關問題