2017-07-27 45 views
13

爲什麼System.IOUtils.TPath.HasValidPathChars接受'?'作爲路徑中的有效字符? 我將第二個參數(UseWildcards)設置爲false。所以,根據文件'?'應該被拒絕。但是,該函數對'c:\ test \ test?\'返回True。爲什麼TPath.HasValidPathChars接受'?'作爲路徑中的有效字符?

UseWildcards =指定是否將掩碼字符視爲 有效路徑字符(例如星號或問號)。

此功能的行爲只是部分正確嗎?該函數是否可以返回更好的結果?

+2

不應拒絕'?',因爲路徑可以在Windows上包含問號。示例:https://superuser.com/q/1069055 –

+0

該超級用戶的帖子還指出:「您不能使用這些類型的路徑來訪問用戶空間中的文件或目錄,只有某些底層系統組件可用於對象管理器路徑「。所以從這個觀點來看,'?'是一個無效的路徑字符。 – gabr

+0

@GünthertheBeautiful - 文章說,\ ??是一個有效的路徑,所以HasValidPathChars應該檢查'??'如果找到了正確的模式(\ ??),並返回true,並且在有單個'?'時返回false。 – Ampere

回答

17

TPath.HasValidPathChars被完全破壞。這是它的實現:

class function TPath.HasValidPathChars(const Path: string; 
    const UseWildcards: Boolean): Boolean; 
var 
    PPath: PChar; 
    PathLen: Integer; 
    Ch: Char; 
    I: Integer; 
begin 
    // Result will become True if an invalid path char is found 
{$IFDEF MSWINDOWS} 
    I := GetPosAfterExtendedPrefix(Path) - 1; 
{$ENDIF MSWINDOWS} 
{$IFDEF POSIX} 
    I := 0; 
{$ENDIF POSIX} 

    PPath := PChar(Path); 
    PathLen := Length(Path); 
    Result := False; 

    while (not Result) and (i < PathLen) do 
    begin 
    Ch := PPath[i]; 
    if not IsValidPathChar(Ch) then 
     if UseWildcards then 
     if not IsPathWildcardChar(Ch) then 
      Result := True 
     else 
      Inc(i) 
     else 
     Result := True 
    else 
     Inc(i); 
    end; 

    Result := not Result; 
end; 

關鍵是要撥打IsValidPathChar。我們來看看它的功能。現在

class function TPath.IsValidPathChar(const AChar: Char): Boolean; 
begin 
    Result := not IsCharInOrderedArray(AChar, FInvalidPathChars); 
end; 

FInvalidPathChars被定義爲:

FInvalidPathChars := TCharArray.Create(
    #0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, 
    #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24, 
    #25, #26, #27, #28, #29, #30, #31, 
    '"', '<', '>', '|');   // DO NOT LOCALIZE; 

即,小於32所有序,並且"<>|

我們還需要了解IsPathWildcardChar的功能。

class function TPath.IsPathWildcardChar(const AChar: Char): Boolean; 
begin 
    Result := IsCharInOrderedArray(AChar, FPathWildcardChars); 
end; 

其中FPathWildcardChars是:

FPathWildcardChars := TCharArray.Create('*', '/', ':', '?', '\'); // DO NOT LOCALIZE; 

現在,回到TPath.HasValidPathChars。讓我們考慮這個if聲明:

if not IsValidPathChar(Ch) then 

條件not IsValidPathChar(Ch)評估爲TrueIsValidPathChar(Ch)False。如果ChFInvalidPathChars中,會發生哪種情況。也就是說,如果Ch具有小於32的序數,或者是",<,>|中的一個。

您的測試字符串是'C:\test\test?\'而實際上這些字符都不在FInvalidPathChars之內。這意味着if not IsValidPathChar(Ch) then聲明中的條件總是評估False。因此,即使你的字符串包含通配符,它​​永遠不能達到的後續測試:

if UseWildcards then 

人們很容易得出結論:HasValidPathChars不論輸入參數UseWildcards的值返回相同的值。如果您對分析的任何疑問,這個程序應該驅散它:

{$APPTYPE CONSOLE} 

uses 
    System.SysUtils, 
    System.IOUtils; 

procedure Main; 
var 
    Ch: Char; 
begin 
    for Ch := low(Ch) to high(Ch) do 
    if TPath.HasValidPathChars(Ch, False)<>TPath.HasValidPathChars(Ch, True) then 
     Writeln('different at #' + IntToStr(ord(Ch))); 
    Writeln('finished'); 
end; 

begin 
    Main; 
    Readln; 
end. 

這看起來像在這又一功能害怕IOUtils單元已被不正當地實施,而不是測試。

我提交了一個報告錯誤:RSP-18696

基於已經偶然發現了IOUtils許多這樣的問題,我的經驗是,該單位不被信任。我不會使用它。找到解決問題的另一種方法。

+0

「很容易得出結論,HasValidPathChars返回相同的值,而不管輸入參數UseWildcards的值如何 - 我只是想明確地說! – Ampere

+0

謝謝大衛。 「我的經驗是單位不被信任」 - 我有自己的'I/O utils'庫,但是當我購買Delphi XE時,我用Embarcadero替換了它,因爲......它是由Embarcadero構建的。 ..所以它一定比我的好...對吧?我不是最好的Delphi程序員,所以我期望Embarcadero最糟糕的程序員至少比我好3倍(他應該是一個真正的Delphi專業人士,對吧?)!!!!!!!!!!!!!!他們如何能夠排除如此巨大的錯誤?可能這就是IDE崩潰的原因:他們在他們的IDE代碼中使用了IOutils :) – Ampere

相關問題