2017-07-27 12 views
13

なぜSystem.IOUtils.TPath.HasValidPathCharsは '?'を受け入れますか?パス内の有効な文字として? 2番目のパラメータ(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が理解する必要があります。

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

さて、戻っTPath.HasValidPathCharsへ:FPathWildcardCharsがある

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

。のは、このifの文を考えてみましょう:IsValidPathChar(Ch)Falseとき

if not IsValidPathChar(Ch) then 

条件not IsValidPathChar(Ch)Trueに評価されます。 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

Davidに感謝します。 「私の経験では、ユニットは信頼できないということです」 - 私は独自の「I/O utils」ライブラリを持っていましたが、EmbarcaderoがDelphi XEを購入したときにEmbarcaderoに置き換えました。 ..それは私のものよりも良くなければなりません...そうですか?私は最高のデルファイプログラマではないので、エンバカデロの最悪のプログラマが私より少なくとも3時間は良いと思っています(真のデルファイプロでなければなりません)!!!!!!!!!!!!!!そのような巨大な間違いをどうやって排除することができますか?おそらくこれがIDEが非常にクラッシュする理由です:IDEコードでIOutilsを使用しました:) – Ampere

関連する問題