Existe-t-il des fonctions standard permettant d'effectuer une conversion de chemin d'accès absolu <-> relatif dans Delphi?
Par exemple:
'C:\Projects\Project1\'
'..\Shared\somefile.pas'
'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\')
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
).
Pour convertir en absolu vous avez:
ExpandFileName
Pour avoir le chemin relatif que vous avez:
ExtraitRelativePath
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
.
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 .
TPath.Combine(S1, S2);
Devrait être disponible depuis Delphi XE.
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;
Une autre solution pour RelToAbs
est simplement:
ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)
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;
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