[英]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.