FindFirst和问号

时间:2016-06-26 12:53:45

标签: delphi findfirst

我需要删除所有文件,这些文件的名称以" a"开头,然后是三个任意字母和" .txt"扩展名如" a123.txt"。这是代码:

var
  sFileMask: string;
  tsrMessage: TSearchRec;
begin
  sFileMask := 'c:/a???.txt';
  if SysUtils.FindFirst(sFileMask, 0, tsrMessage) = 0 then
  begin
    repeat
      ShowMessage(tsrMessage.Name);
    until FindNext(tsrMessage) <> 0;
    SysUtils.FindClose(tsrMessage);
  end;
end;

我一直认为问号意味着一个且只有一个字符,但令我惊讶的是,这个代码返回&#34; a.txt&#34;,&#34; a1.txt&#34;和&#34; a123.txt&#34;文件名。是否有一种简单的方法可以修改代码,只搜索&#34; a123.txt&#34;等文件?

2 个答案:

答案 0 :(得分:4)

此行为与设计完全相同。 Raymond Chen在此解释:How did wildcards work in MS-DOS?

您将从命令解释程序中看到完全相同的行为。

C:\Desktop>dir a???.txt
 Volume in drive C has no label.
 Volume Serial Number is 20DA-7FEB

 Directory of C:\Desktop

26/06/2016  14:03                 6 a.txt
26/06/2016  14:03                 6 a1.txt
26/06/2016  14:03                 6 a12.txt
26/06/2016  14:03                 6 a123.txt
               4 File(s)             24 bytes
               0 Dir(s)  286,381,445,120 bytes free

无法说服FindFirstFile(Windows上RTL&lt; FindFirst背后的API)按照您的意愿行事。您最好的选择是枚举整个目录,并使用您选择的模式匹配算法执行自己的过滤。

答案 1 :(得分:4)

满足您特定需求的最简单的解决方案是替换它:

ShowMessage(tsrMessage.Name);

用这个

if length(tsrMessage.Name)=8 then ShowMessage(tsrMessage.Name);

这将确保文件名的长度恰好是四个字符+句点+扩展名。就像David说的那样,没有办法让API进行这种过滤,所以你必须自己做,但在你的特定情况下,没有必要枚举整个目录。您至少可以让API执行可以做的过滤,然后在其上进行自己的过滤。

编辑:如果你需要确保&#34; a&#34;之后的三个字符。是数字,你可以这样做:

if (length(tsrMessage.Name)=8) and tsrMessage[2].IsDigit and tsrMessage[3].IsDigit and tsrMessage[4].IsDigit then ShowMessage(tsrMessage.Name);

如果您使用的是现代编译器(您需要包含&#34; Characters&#34;单元)。另请注意,如果您正在编译移动版本,则需要使用索引[1],[2]和[3],因为它们在字符串的0处开始索引。

如果您使用的是旧版本,可以这样做:

function IsDigit(c : char) : boolean;
  begin
    Result:=(c>='0') and (c<='9')
  end;

if (length(tsrMessage.Name)=8) and IsDigit(tsrMessage[2]) and IsDigit(tsrMessage[3]) and IsDigit(tsrMessage[4]) then ShowMessage(tsrMessage.Name);