簡體   English   中英

FindFirst和問號

[英]FindFirst and question mark

我需要刪除所有以“ 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;

我一直以為問號表示一個字符,但只有一個字符,但令我驚訝的是,該代碼返回了“ a.txt”,“ a1.txt”和“ a123.txt”文件名。 是否有一種簡單的方法可以修改代碼以僅查找“ a123.txt”之類的文件?

此行為是設計使然。 Raymond Chen對此進行了解釋: 通配符如何在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的FindFirst背后的API)以您希望的方式運行。 最好的選擇是枚舉整個目錄,並使用選擇的模式匹配算法執行自己的過濾。

滿足您特定需求的最簡單的解決方案是替換為:

ShowMessage(tsrMessage.Name);

有了這個

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

這樣可以確保文件名的長度正好是四個字符+句點+擴展名。 就像David所說的那樣,沒有辦法讓API進行這種過濾,因此您必須自己做,但是在您的特殊情況下,不需要枚舉整個目錄。 您至少可以讓API做它可以做的過濾,然后在它上面做自己的過濾。

編輯:如果您需要確保“ a”后面的三個字符是數字,則可以這樣進行:

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

如果您使用的是現代編譯器(您需要包括“字符”單元)。 另請注意,如果要編譯移動版本,則需要使用索引[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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM