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
に評価されます。 Ch
がFInvalidPathChars
にある場合に発生します。つまり、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
でこのような多くの問題が発生したことに基づいて、私の経験では、ユニットは信頼できないということです。私はそれを使用しません。あなたの問題を解決する別の方法を見つける。
パスにWindows上で疑問符が含まれる可能性があるため、 '?'を拒否しないでください。例:https://superuser.com/q/1069055 –
スーパーユーザー投稿には、次のように書かれています。「ユーザースペース内のファイルやディレクトリにアクセスするために、この種のパスを使用することはできません。オブジェクトマネージャパス。したがって、この観点から、 '?'は無効なパス文字です。 – gabr
@GünthertheBeautiful - 記事では、\は有効なパスなので、HasValidPathCharsは '??'をチェックする必要があります。正しいパターン(¥??)が見つかった場合はtrueを返し、単一の '?'がある場合はfalseを返します。 – Ampere