web-dev-qa-db-fra.com

Conversion entre les chemins absolus et relatifs dans Delphi

Existe-t-il des fonctions standard permettant d'effectuer une conversion de chemin d'accès absolu <-> relatif dans Delphi?

Par exemple:

  • Le chemin de base est 'C:\Projects\Project1\'
  • Le chemin relatif est '..\Shared\somefile.pas'
  • Le chemin absolu est 'C:\Projects\Shared\somefile.pas'

Je cherche quelque chose comme ça:

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\')  
33
kludg

J'utiliserais PathRelativePathTo comme première fonction et PathCanonicalize comme seconde. Dans ce dernier cas, en tant qu'argument, vous transmettez la somme de chaîne du chemin de base et du chemin relatif.

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;

Bien entendu, si vous utilisez une version non Unicode de Delphi (<= Delphi 2007), vous devez utiliser les fonctions Ansi (*A) au lieu des fonctions Unicode (*W).

32
Andreas Rejbrand

Pour convertir en absolu vous avez:

ExpandFileName

Pour avoir le chemin relatif que vous avez:

ExtraitRelativePath

45
philnext

Pour ce que ça vaut, ma base de code utilise SysUtils.ExtractRelativePath dans un sens et le wrapper développé par nos soins suivant:

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;

Vous devrez utiliser l'unité ShLwApi pour PathIsRelative et PathCanonicalize.

L'appel à PathIsRelative signifie que la routine est robuste aux chemins absolus spécifiés.

Donc, SysUtils.ExtractRelativePath peut être votre AbsToRel, seuls les paramètres sont inversés. Et ma ExpandFileNameRelBaseDir vous servira de RelToAbs.

12
David Heffernan

Je viens de préparer cela ensemble:

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;

Merci à Andreas et David d’avoir attiré mon attention sur le Fonctions de gestion des chemins d’échantillonnage .

5
Uli Gerhardt
TPath.Combine(S1, S2);

Devrait être disponible depuis Delphi XE.

2
ZzZombo

Vérifiez si votre solution fonctionnera avec le chemin relatif vers le chemin complet au cas où vous modifieriez le répertoire en cours. Cela fonctionnera:

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

Une autre solution pour RelToAbs est simplement:

ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)
1

Une autre version de RelToAbs (compatible avec toutes les versions de 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
SuatDmk

Je ne sais pas trop si cela sera encore nécessaire après 2 ans ou plus, mais voici un moyen d'obtenir la réponse relative à absolue (comme pour absolue à relative, je suggérerais philnext 's ExtractRelativePath answer):

Unité: IOUtils

Parent: TPath

function GetFullPath(const BasePath: string): string;

Il renverra le chemin absolu complet pour un chemin relatif donné. Si le chemin donné est déjà absolu, il le retournera tel quel.

Voici le lien sur Embarcadero: Obtenir le chemin complet

Et voici un lien pour Routines de manipulation de chemin

0
user4473626