delphi - una - url relativos y absolutos
ConversiĆ³n entre rutas absolutas y relativas en Delphi (9)
¿Hay funciones estándar para realizar la conversión de ruta relativa absoluta <-> en Delphi?
Por ejemplo:
- La ruta ''Base'' es
''C:/Projects/Project1/'
- La ruta relativa es
''../Shared/somefile.pas''
- La ruta absoluta es
''C:/Projects/Shared/somefile.pas''
Estoy buscando algo como esto:
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/')
Acabo de elaborar esto juntos:
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;
Gracias a Andreas y David por llamar mi atención sobre las funciones de manejo de la ruta de Shell .
Compruebe si su solución funcionará con la ruta relativa a la ruta completa en caso de que cambie el directorio actual. Esto funcionará:
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;
No estoy muy seguro de si esto todavía es necesario después de más de 2 años, pero aquí hay una manera de hacer que el Relativo sea Absoluto (En cuanto a Absoluto a Relativo sugeriría la respuesta ExtractRelativePath
):
Unidad: IOUtils
Padre: TPath
function GetFullPath(const BasePath: string): string;
Devolverá la ruta completa y absoluta para una ruta relativa dada. Si la ruta dada ya es absoluta, simplemente la devolverá tal como está.
Aquí está el enlace en Embarcadero: Get Full Path
Y aquí hay un enlace para Rutinas de Manipulación de Caminos
Otra versión de RelToAbs (compatible con todas las versiones 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;
Para convertir a lo absoluto tienes:
ExpandFileName
Para tener la ruta relativa que tiene:
ExtractRelativePath
Por lo que vale, mi base de código usa SysUtils.ExtractRelativePath
en una dirección y regresa la siguiente envoltura local:
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;
Tendrá que usar la unidad PathIsRelative
para PathIsRelative
y PathCanonicalize
.
La llamada a PathIsRelative
significa que la rutina es robusta para las rutas absolutas que se especifican.
Entonces, SysUtils.ExtractRelativePath
puede ser su AbsToRel
solo los parámetros están invertidos. Y mi ExpandFileNameRelBaseDir
servirá como tus RelToAbs
.
Una solución alternativa para RelToAbs
es simplemente:
ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)
Utilizaría PathRelativePathTo
como la primera función y PathCanonicalize
como el segundo. En el último caso, como argumento, pasa la suma de cadena de la ruta base y la ruta relativa.
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;
Por supuesto, si utiliza una versión de Delphi que no es Unicode (es decir, <= Delphi 2007), debe usar las funciones Ansi ( *A
) en lugar de las funciones Unicode ( *W
).
TPath.Combine(S1, S2);
Debería estar disponible desde Delphi XE.