Konwersja ścieżek bezwzględnych i względnych w Delphi

Czy istnieją standardowe funkcje do wykonywania bezwzględnej względnej konwersji ścieżki w Delphi?

Na przykład:

  • ' base ' path is 'C:\Projects\Project1\'
  • ścieżka względna to '..\Shared\somefile.pas'
  • ścieżka absolutna to 'C:\Projects\Shared\somefile.pas'

Szukam czegoś takiego:

function AbsToRel(const AbsPath, BasePath: string): string;
// '..\Shared\somefile.pas' =
//   AbsToRel('C:\Projects\Shared\somefile.pas', 'C:\Projects\Project1\')  
function RelToAbs(const RelPath, BasePath: string): string;
// 'C:\Projects\Shared\somefile.pas' =
//   RelToAbs('..\Shared\somefile.pas', 'C:\Projects\Project1\')  
 32
Author: Jerry Dodge, 2011-03-16

9 answers

Użyłbym PathRelativePathTo jako pierwsza funkcja i PathCanonicalize jako drugi. W tym drugim przypadku, jako argument przekazujesz sumę łańcuchów ścieżki podstawowej i ścieżki względnej.

function PathRelativePathTo(pszPath: PChar; pszFrom: PChar; dwAttrFrom: DWORD;
  pszTo: PChar; dwAtrTo: DWORD): LongBool; stdcall; external 'shlwapi.dll' name 'PathRelativePathToW';

function AbsToRel(const AbsPath, BasePath: string): string;
var
  Path: array[0..MAX_PATH-1] of char;
begin
  PathRelativePathTo(@Path[0], PChar(BasePath), FILE_ATTRIBUTE_DIRECTORY, PChar(AbsPath), 0);
  result := Path;
end;

function PathCanonicalize(lpszDst: PChar; lpszSrc: PChar): LongBool; stdcall;
  external 'shlwapi.dll' name 'PathCanonicalizeW';

function RelToAbs(const RelPath, BasePath: string): string;
var
  Dst: array[0..MAX_PATH-1] of char;
begin
  PathCanonicalize(@Dst[0], PChar(IncludeTrailingBackslash(BasePath) + RelPath));
  result := Dst;
end;


procedure TForm4.FormCreate(Sender: TObject);
begin
  ShowMessage(AbsToRel('C:\Users\Andreas Rejbrand\Desktop\file.txt', 'C:\Users\Andreas Rejbrand\Pictures'));
  ShowMessage(RelToAbs('..\Videos\movie.wma', 'C:\Users\Andreas Rejbrand\Desktop'));
end;

Oczywiście, jeśli używasz innej niż Unicode wersji Delphi (tj. *A) zamiast funkcji Unicode (*W).

 30
Author: Andreas Rejbrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-16 20:30:43

Aby przekonwertować na Absolut MASZ:

ExpandFileName

Aby mieć ścieżkę względną:

ExtractRelativePath

 44
Author: philnext,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-16 18:29:52

Jeśli to coś warte, moja baza kodowa używa SysUtils.ExtractRelativePath w jednym kierunku i następujące domowe opakowanie wraca:

function ExpandFileNameRelBaseDir(const FileName, BaseDir: string): string;
var
  Buffer: array [0..MAX_PATH-1] of Char;
begin
  if PathIsRelative(PChar(FileName)) then begin
    Result := IncludeTrailingBackslash(BaseDir)+FileName;
  end else begin
    Result := FileName;
  end;
  if PathCanonicalize(@Buffer[0], PChar(Result)) then begin
    Result := Buffer;
  end;
end;

Musisz użyć jednostki ShLwApi dla PathIsRelative i PathCanonicalize.

Wywołanie PathIsRelative oznacza, że funkcja jest odporna na definiowanie ścieżek bezwzględnych.

Więc SysUtils.ExtractRelativePath może być twoje AbsToRel tylko parametry są odwrócone. A mój ExpandFileNameRelBaseDir będzie służył jako twój RelToAbs.

 12
Author: David Heffernan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-07 13:39:48

Właśnie zaparzyłem to razem:

uses
  ShLwApi;

function RelToAbs(const ARelPath, ABasePath: string): string;
begin
  SetLength(Result, MAX_PATH);
  if PathCombine(@Result[1], PChar(IncludeTrailingPathDelimiter(ABasePath)), PChar(ARelPath)) = nil then
    Result := ''
  else
    SetLength(Result, StrLen(@Result[1]));
end;

Podziękowania dla Andreasa i Davida za zwrócenie mojej uwagi nafunkcje obsługi ścieżek powłoki .

 5
Author: Uli Gerhardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-17 08:27:12
TPath.Combine(S1, S2);

Powinny być dostępne od Delphi XE.

 2
Author: ZzZombo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 03:29:56

Alternatywnym rozwiązaniem dla RelToAbs jest po prostu:

ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)
 1
Author: Jarrod Hollingworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-08 04:59:07

Sprawdź, czy Twoje rozwiązanie będzie działać ze ścieżką względną do pełnej ścieżki w przypadku zmiany bieżącego katalogu. To zadziała:

function PathRelativeToFull(APath : string) : string;
var
  xDir : string;
begin
  xDir := GetCurrentDir;
  try
    SetCurrentDir('C:\Projects\Project1\');
    Result := ExpandFileName(APath);
  finally
    SetCurrentDir(xDir);
  end{try..finally};
end;

function PathFullToRelative(APath : string; ABaseDir : string = '') : string;
begin
  if ABaseDir = '' then
    ABaseDir := 'C:\Projects\Project1\';
  Result := ExtractRelativePath(ABaseDir, APath);
end;
 1
Author: Alexandr Morozevich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-20 07:19:58

Nie jestem zbyt pewien, czy jest to nadal potrzebne po 2+ latach, ale tutaj jest sposób, aby uzyskać względny do absolutnego (co do absolutnego do względnego sugerowałbym philnext ' s ExtractRelativePath ODPOWIEDŹ):

Jednostka: IOUtils

Rodzic: TPath

function GetFullPath(const BasePath: string): string;

Zwróci pełną, bezwzględną ścieżkę dla danej ścieżki względnej. Jeśli dana ścieżka jest już absolutna, po prostu zwróci ją tak, jak jest.

Tutaj jest link do Embarcadero: Pobierz pełną ścieżkę

A oto link do procedury manipulacji ścieżką

 0
Author: user4473626,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:36

Kolejna wersja RelToAbs (kompatybilna ze wszystkimi wersjami Delphi XE).

uses
  ShLwApi;

    function RelPathToAbsPath(const ARelPath, ABasePath: string): string;
    var Buff:array[0..MAX_PATH] of Char;
    begin
      if PathCombine(Buff, PChar(IncludeTrailingPathDelimiter(ABasePath)), PChar(ARelPath)) = nil then
        Result := ''
      else Result:=Buff;
    end;
 0
Author: SuatDmk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-11 14:37:16