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

时间:2011-03-16 17:47:08

标签: 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\')  

9 个答案:

答案 0 :(得分:47)

要转换为您拥有的绝对值:

  

ExpandFileName

拥有相对路径:

  

ExtractRelativePath

答案 1 :(得分:33)

我会使用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;

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

答案 2 :(得分: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;

您需要将ShLwApi单位用于PathIsRelativePathCanonicalize

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

因此,SysUtils.ExtractRelativePath可以是您的AbsToRel只有参数被反转。我的ExpandFileNameRelBaseDir将作为您的RelToAbs

答案 3 :(得分: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;

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

答案 4 :(得分:2)

TPath.Combine(S1, S2);

自Delphi XE以来应该可用。

答案 5 :(得分:1)

RelToAbs的替代解决方案很简单:

ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)

答案 6 :(得分:1)

如果您更改当前目录,请检查您的解决方案是否适用于相对路径到完整路径。这将有效:

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;

答案 7 :(得分:0)

我不太确定2年以后是否还需要这个,但这里有一种方法可以让相对于绝对(至于绝对相对我会建议philnext' s {{ 1}}回答):

单位:IOUtils

父母:TPath

ExtractRelativePath

它将返回给定相对路径的完整绝对路径。如果给定路径已经是绝对路径,它将按原样返回。

以下是Embarcadero的链接:Get Full Path

这是Path Manipulation Routines

的链接

答案 8 :(得分:0)

RelToAbs的另一个版本(与所有Delphi XE版本兼容)。

Node.childNodes