2017-07-27 72 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

相关问题