Delphi中绝对路径和相对路径之间的转换

klu*_*udg 37 delphi path

是否有标准函数在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\')  
Run Code Online (Sandbox Code Playgroud)

phi*_*ext 48

要转换为绝对你有:

ExpandFileName

拥有相对路径:

ExtractRelativePath

  • ExpandFileName在这里不好用.它使用工作目录而不是用户指定的目录.你将需要像安德烈亚斯的答案或我自己的答案. (9认同)

And*_*and 34

我将使用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;
Run Code Online (Sandbox Code Playgroud)

当然,如果使用非Unicode版本的Delphi(即<= Delphi 2007),则需要使用Ansi函数(*A)而不是Unicode函数(*W).

  • 请注意,RelToAbs仅在RelPath确实是相对路径时才有效.如果它是绝对路径,那么它将失败.在实际应用中,拥有一个对此具有弹性的函数是很好的,因为通常允许用户指定绝对路径或相对路径. (3认同)
  • 无需自己声明PathCanonicalize,只需将其从ShLwApi中取出即可 (2认同)

Dav*_*nan 12

为了它的价值,我的代码库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;
Run Code Online (Sandbox Code Playgroud)

您需要将该ShLwApi装置用于PathIsRelativePathCanonicalize.

调用PathIsRelative意味着例程对指定的绝对路径是健壮的.

所以,SysUtils.ExtractRelativePath可以将您AbsToRel唯一的参数反转.而我的ExpandFileNameRelBaseDir意志将成为你的RelToAbs.


Uli*_*rdt 5

我只是一起酿造:

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;
Run Code Online (Sandbox Code Playgroud)

感谢Andreas和David引起我对Shell Path Handling Functions的注意.