2017-07-27 50 views
13

Tại sao System.IOUtils.TPath.HasValidPathChars chấp nhận '?' như một char hợp lệ trong một con đường? Tôi đặt tham số thứ hai (UseWildcards) thành false. Vì vậy, theo tài liệu '?' nên bị từ chối. Tuy nhiên, hàm trả về True cho 'c: \ test \ test? \'.Tại sao TPath.HasValidPathChars chấp nhận '?' như một char hợp lệ trong một con đường?

UseWildcards = Chỉ định xem các ký tự mặt nạ có được coi là ký tự đường dẫn hợp lệ (ví dụ: dấu hoa thị hoặc dấu hỏi).

Hành vi của chức năng này chỉ đúng một phần? Có thể hàm đã trả lại kết quả tốt hơn không?

+2

Không nên từ chối '?' Vì đường dẫn CÓ THỂ chứa dấu hỏi trên Windows. Ví dụ: https://superuser.com/q/1069055 –

+0

Bài đăng siêu người dùng đó cũng nêu rõ: "Bạn không thể sử dụng các loại đường dẫn này để truy cập tệp hoặc thư mục trong vùng người dùng. Chỉ một số thành phần hệ thống cấp thấp nhất định được thiết kế để hoạt động với Đường dẫn Trình quản lý đối tượng. " Vì vậy, từ quan điểm này '?' Là một ký tự đường dẫn không hợp lệ. – gabr

+0

@ GünthertheBeautiful - Bài viết nói rằng \ ?? là một đường dẫn hợp lệ, vì vậy HasValidPathChars nên kiểm tra '??' và trả về true NẾU mẫu đúng (\ ??) được tìm thấy và sai khi có một '?' – Ampere

Trả lời

17

TPath.HasValidPathChars hoàn toàn bị hỏng. Đây là triển khai của nó:

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; 

Điểm quan trọng là gọi tới IsValidPathChar. Hãy nhìn vào những gì có.

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

Bây giờ, FInvalidPathChars được định nghĩa là:

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; 

Đó là, tất cả ordinals ít hơn 32 tuổi, và ", <, >|.

Chúng tôi cũng cần hiểu những gì IsPathWildcardChar thực hiện.

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

đâu FPathWildcardChars là:

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

Bây giờ, trở lại TPath.HasValidPathChars. Hãy xem xét if tuyên bố này:

if not IsValidPathChar(Ch) then 

Điều kiện not IsValidPathChar(Ch) đánh giá để True khi IsValidPathChar(Ch)False. Điều này xảy ra nếu Ch nằm trong số FInvalidPathChars. Đó là nếu Ch có thứ tự dưới 32 hoặc là một trong số ", <, >|.

Chuỗi kiểm tra của bạn là 'C:\test\test?\' và trên thực tế không có ký tự nào trong số này là FInvalidPathChars. Điều này có nghĩa là điều kiện trong câu lệnh if not IsValidPathChar(Ch) then luôn đánh giá False. Vì vậy, mặc dù chuỗi của bạn có chứa một ký tự đại diện, nó không bao giờ có thể đạt được thử nghiệm tiếp theo:

if UseWildcards then 

Nó rất dễ dàng để kết luận rằng HasValidPathChars trả về giá trị như nhau không phụ thuộc vào giá trị của tham số đầu vào UseWildcards. Và nếu bạn có bất kỳ nghi ngờ gì về việc phân tích, chương trình này nên xua tan nó:

{$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. 

này trông giống như thêm một chức năng trong này sợ hãi IOUtils đơn vị đó đã được thực hiện không đúng cách và không được kiểm tra.

Tôi đã gửi báo cáo lỗi: RSP-18696.

Dựa trên việc vấp phải nhiều vấn đề như vậy với IOUtils, kinh nghiệm của tôi là đơn vị không được tin cậy. Tôi sẽ không sử dụng nó. Tìm một cách khác để giải quyết vấn đề của bạn.

+0

"Nó rất dễ dàng để kết luận rằng HasValidPathChars trả về cùng một giá trị không phân biệt giá trị của tham số đầu vào UseWildcards" - Tôi chỉ muốn nói chính xác điều đó !!! – Ampere

+0

Cảm ơn David. "kinh nghiệm của tôi là đơn vị không được tin cậy" - Tôi có thư viện 'I/O utils' của riêng mình nhưng tôi đã thay thế nó bằng Embarcadero khi tôi mua Delphi XE vì ... tốt ... nó được xây dựng bởi Embarcadero. .. vì vậy nó phải tốt hơn tôi ... phải không? Tôi không phải là lập trình viên Delphi hàng đầu vì vậy tôi hy vọng rằng lập trình viên tồi tệ nhất tại Embarcadero sẽ có ít nhất 3 lần tốt hơn tôi (anh ta phải là một TRUE Delphi chuyên nghiệp, phải không?) !!!!!!!!!!!!!! Làm thế nào họ có thể cho ra những sai lầm lớn như vậy ra? Có lẽ đây là lý do tại sao IDE bị treo rất nhiều: họ đã sử dụng IOutils trong mã IDE của họ :) – Ampere

Các vấn đề liên quan