使用Delphi在目录中查找最旧文件的最快方法

时间:2010-03-23 12:30:09

标签: delphi file datetime

HI

我们有大量远程计算机可将视频捕获到磁盘驱动器上。每个摄像头都有自己独特的目录,任何一个磁盘上最多可以有16个目录。

我正在尝试找到磁盘上最旧的视频文件,但使用FindFirst/FindNext来比较文件创建日期时间需要永久。

有人知道找到目录中最旧文件的更有效方法吗?我们从HO中心位置远程连接到电脑。

问候,彼得

- 更新

谢谢大家的答案。最后我使用了以下内容。

  1. 使用windows.WNetAddConnection2
    将驱动器('w:')映射到远程计算机 //使用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. //使用windows.WNetCancelConnection2
  5. 断开与远程计算机的连接

4 个答案:

答案 0 :(得分:1)

您还可以尝试FindFirstFileEx FindExInfoBasic参数,在Windows 7或Server 2008 R2或更高版本,FIND_FIRST_EX_LARGE_FETCH should improve performance

答案 1 :(得分:0)

首先,从how to run a DOS program and pipe its output to a TStrings上的此页面获取RunDosAppPipedToTStrings例程。该示例使用TMemo的Lines属性,但您可以传入任何TStrings,例如TStringList。请注意,如果CreateProcess返回false,这将无提示失败。您可能希望将 else 大小写添加到引发异常的“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;

然后剩下要做的就是解析输出,提取日期和时间以及文件名,按日期和时间排序,并获取具有最低日期的文件的文件名。我会给你留下那么多。

答案 2 :(得分:0)

如果你可以在远程计算机上运行可以迭代目录的东西,那将是最快的方法。如果您想使用Mason的示例,请尝试使用来自SysInternals的PsExec启动它。

如果你只能在本地运行一个应用程序,那么就没有比FindFirst / FindNext更快的方法,你做的任何事情最终都会归结为最终。如果您的本地计算机运行的是Windows 7,则可以使用FindFirstFileEx,它有标志表示它应该使用更大的缓冲区进行传输,并且它不应该读取8.3别名,这可以帮助提高速度。

答案 3 :(得分: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;

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