2010-03-23 35 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; 

我知道这不是最好的解决方案,但适用于我。

相关问题