Search code examples
filedelphifilepath

How to get the path to the file using backslash symbol and 2 dots ('\..')


In Delphi program I use ExtractFileDir function for getting parent folder and this code works correctly:

Fmain.frxReport1.LoadFromFile(ExtractFileDir(ExtractFileDir(ExtractFileDir(ExtractFilePath(ParamStr(0)))))+'\FastReports\report1.fr3');

How can I modify it and get parent folder's path with using "\.." as it is realised in Delphi sample program

enter image description here

Update:

I wrote this code:

setcurrentdir('../../');
 s1:=getcurrentdir();
 frxReport1.LoadFromFile(s1+'\FastReports\report1.fr3');

but I want one-line(as my code with ExtractFileDir ) and well-readable code to replace my code.


Solution

  • I have a function which absolutize a relative path. To absolutize a path, you need to know the base path.

    I the case of Delphi you show, the paths are relative to the project directory.

    Once you have an absolute path, you can apply ExtractFilePath several times to go up in the directory levels.

    Let's take an example: You have a relative path "....\SomeFile.txt". This path is relative to the base path "C:\ProgramData\Acme\Project\Demo". The complete path is: "C:\ProgramData\Acme\Project\Demo....\SomeFile.txt". Then the absolute path result of AbsolutizePath will be "C:\ProgramData\Acme\SomeFile.txt".

    Note that Absolutize path take care of ".." (parent directory), "." (Current directory) and drive specification (Such as C:).

    function AbsolutizePath(
        const RelPath  : String;
        const BasePath : String = '') : String;
    var
        I, J : Integer;
    begin
        if RelPath = '' then
            Result := BasePath
        else if RelPath[1] <> '\' then begin
            if (BasePath = '') or
               ((Length(RelPath) > 1) and (RelPath[2] = ':')) then
                Result := RelPath
            else
                Result := IncludeTrailingPathDelimiter(BasePath) + RelPath;
        end
        else
            Result := RelPath;
        // If there is no drive in the result, add the one from base if any
        if (Length(Result) > 1) and (Result[2] <> ':') and
           (Length(BasePath) > 1) and (BasePath[2] = ':') then
            Insert(Copy(BasePath, 1, 2), Result, 1);
        // Delete "current dir" marker
        I := 1;
        while TRUE do begin
            I := Pos('\.\', Result, I);
            if I <= 0 then
                break;
            Delete(Result, I, 2);
        end;
        // Process "up one level" marker
        I := 1;
        while TRUE do begin
            I := Pos('\..\', Result, I);
            if I <= 0 then
                break;
            J := I - 1;
            while (J > 0) and (not CharInSet(Result[J], ['\', ':'])) do
                Dec(J);
            // Check if we hit drive delimiter and fix it
            if (J = 2) and (Result[J] = ':') then
                J := 3;
            Delete(Result, J + 1, I - J + 3);
            I := J;
        end;
    end;