TPath.HasValidPathChars
est complètement cassé. Ceci est sa mise en œuvre:
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;
Le point crucial est l'appel à IsValidPathChar
. Regardons ce que ça fait.
class function TPath.IsValidPathChar(const AChar: Char): Boolean;
begin
Result := not IsCharInOrderedArray(AChar, FInvalidPathChars);
end;
Maintenant, FInvalidPathChars
est défini comme:
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;
C'est, ordinaux moins de 32, et "
, <
, >
et |
.
Nous devons également comprendre ce que fait IsPathWildcardChar
.
class function TPath.IsPathWildcardChar(const AChar: Char): Boolean;
begin
Result := IsCharInOrderedArray(AChar, FPathWildcardChars);
end;
Où FPathWildcardChars
est:
FPathWildcardChars := TCharArray.Create('*', '/', ':', '?', '\'); // DO NOT LOCALIZE;
Maintenant, retour à TPath.HasValidPathChars
. Considérons cette déclaration if
:
if not IsValidPathChar(Ch) then
La condition not IsValidPathChar(Ch)
est évaluée à True
quand IsValidPathChar(Ch)
est False
. Ce qui se passe si Ch
est dans FInvalidPathChars
. C'est-à-dire si Ch
a un ordinal inférieur à 32, ou est l'un de "
, <
, >
et |
. Votre chaîne de test est 'C:\test\test?\'
et aucun de ces caractères n'est en FInvalidPathChars
Ce qui signifie que la condition dans l'instruction if not IsValidPathChar(Ch) then
évalue toujours False
. Ainsi, même si votre chaîne contient un caractère générique, il ne peut jamais atteindre le test suivant:
if UseWildcards then
Il est facile de conclure que HasValidPathChars
retourne la même valeur quelle que soit la valeur du paramètre d'entrée UseWildcards
. Et si vous avez un doute sur l'analyse, ce programme devrait dissiper:
{$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.
Cela ressemble à une autre fonction dans cette unité IOUtils
redoutée qui a été mal mis en œuvre et non testés.
J'ai soumis un rapport de bogue: RSP-18696.
D'après avoir trébuché sur beaucoup de ces problèmes avec IOUtils
, mon expérience est que l'unité ne doit pas être digne de confiance. Je ne l'utiliserais pas. Trouvez une solution alternative pour résoudre votre problème.
Les ''? Ne doit pas être rejeté parce que les chemins peuvent contenir des points d'interrogation sur Windows. Exemple: https://superuser.com/q/1069055 –
Ce poste de super-utilisateur indique également: « Vous ne pouvez pas utiliser ces types de chemins pour accéder à des fichiers ou des répertoires dans l'espace utilisateur Seuls certains composants du système à faible niveau sont conçus pour fonctionner avec. Chemins du gestionnaire d'objets. " Donc, de ce point de vue, '?' Est un caractère de chemin invalide. – gabr
@ GünthertheBeautiful - L'article dit que \ ?? est un chemin valide, donc HasValidPathChars devrait vérifier '??' et retourne true SI le motif correct (\ ??) est trouvé et false quand il y a un seul '?' – Ampere