Подтвердить что ты не робот

Преобразование между абсолютными и относительными путями в Delphi

Существуют ли стандартные функции для выполнения абсолютного &lt - - относительного преобразования пути в Delphi?

Например:

  • "Базовый" путь 'C:\Projects\Project1\'
  • Относительный путь '..\Shared\somefile.pas'
  • Абсолютный путь 'C:\Projects\Shared\somefile.pas'

Я ищу что-то вроде этого:

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\')  
4b9b3361

Ответ 1

Я использовал бы PathRelativePathTo в качестве первой функции и PathCanonicalize как второй. В последнем случае в качестве аргумента вы передаете строчную сумму базового пути и относительного пути.

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;

Конечно, если вы используете версию Delphi, отличную от Unicode (то есть, <= Delphi 2007), вам нужно использовать функции Ansi (*A) вместо функций Unicode (*W).

Ответ 2

Чтобы преобразовать в абсолют, вы имеете:

ExpandFileName

Чтобы иметь относительный путь:

ExtractRelativePath

Ответ 3

Для того, что стоит, моя кодовая база использует SysUtils.ExtractRelativePath в одном направлении, и следующая домашняя обертка возвращается:

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;

Вам понадобится блок ShLwApi для PathIsRelative и PathCanonicalize.

Вызов PathIsRelative означает, что подпрограмма является надежной для заданных абсолютных путей.

Итак, SysUtils.ExtractRelativePath может быть вашим AbsToRel, только параметры меняются на противоположные. И мой ExpandFileNameRelBaseDir будет служить вашим RelToAbs.

Ответ 4

Я просто сварил это вместе:

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;

Спасибо Андреасу и Дэвиду за то, что обратили мое внимание на Функции управления трассировкой оболочки.

Ответ 5

TPath.Combine(S1, S2);

Должно быть доступно с Delphi XE.

Ответ 6

Альтернативное решение для RelToAbs просто:

ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)

Ответ 7

Проверьте, будет ли ваше решение работать с Relative Path To Full Path в случае изменения текущего каталога. Это будет работать:

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;

Ответ 8

Я не слишком уверен, что это все еще необходимо после 2+ лет, но вот способ получить отношение к абсолютному (Что касается абсолютного относительного, я бы предложил philnext ExtractRelativePath ответ):

Единица: IOUtils

Родитель: TPath

function GetFullPath(const BasePath: string): string;

Он вернет полный, абсолютный путь для данного относительного пути. Если данный путь уже является абсолютным, он просто вернет его как есть.

Вот ссылка на Embarcadero: Получить полный путь

И вот ссылка для Процедуры манипулирования трафиком

Ответ 9

Другая версия RelToAbs (совместимая со всеми версиями 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;