Delphi中绝对路径与相对路径的转换

Delphi中绝对路径与相对路径的转换,delphi,path,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:

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\')  
我将用作第一个函数和第二个函数。在后一种情况下,作为参数传递基本路径和相对路径的字符串和

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(即,转换为绝对值):

扩展文件名

要获得您拥有的相对路径,请执行以下操作:

相对提取器


值得一提的是,我的代码库在一个方向上使用了
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;
对于
PathIsRelative
pathcononicalize
,您需要使用
ShLwApi
单元

PathIsRelative
的调用意味着例程对指定的绝对路径具有鲁棒性


因此,
SysUtils.ExtractRelativePath
可以作为您的
Absorel
只有参数是反向的。而我的
ExpandFileNameRelBaseDir
将作为您的
RelToAbs

我刚刚一起酿造了这个:

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提醒我注意。

我不太确定2年多后是否还需要这样做,但这里有一种方法可以获得相对到绝对(至于绝对到相对,我建议的
提取相对路径
答案):

单位:IOUtils

家长:TPath

function GetFullPath(const BasePath: string): string;
它将返回给定相对路径的完整绝对路径。如果给定路径已经是绝对路径,它将按原样返回

以下是Embarcadero的链接:


这里有一个链接

关于
reltoab
的另一个解决方案是:

ExpandFileName(IncludeTrailingPathDelimiter(BasePath) + RelPath)

应在Delphi XE之后可用。

检查您的解决方案是否可以在更改当前目录时使用相对路径到完整路径。这将起作用:

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;

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


@安德烈亚斯:是的,但它需要一些工作来适应这个问题。ExpandFileName在这里不好。它使用的是工作目录,而不是用户指定的目录。您将需要类似安德烈亚斯的答案或我自己的答案。尽管作为一个补充,如果您像我一样想解析/data/whater/parent/child//到/data/whater/parent/child-这个ExpandFileName非常有用,而且是跨平台的。无需声明PathCanonicalize,只需将其从ShLwApi@David:是的,我现在明白了。请注意,只有当RelPath真的是一个相对路径时,RelToAbs才有效。如果它是一个绝对路径,那么它将失败。在实际应用中,最好有一个at对此很有弹性,因为通常您允许用户指定绝对或相对路径。我假设
TWin32PathBuffer
数组[0..MAX\u PATH-1]关于char
?@Andreas正确,谢谢。从代码中挑出一些片段,然后使其独立起来总是很有趣的。我是一个upvoter,不是downvoter,除了你的评论中的一个输入错误之外,我没有看到任何错误:*他们没有,也许@downvoter给了你-1,因为你没有指定什么模块(
Windows
ShLwApi
)是编译示例所必需的“最佳”答案也没有指定。还有一件事:变量
s
已声明但未使用。是绝对路径“C:\Projects\Shared\somefile.pas”或“C:\Projects\Project1\Shared\somefile.pas”?@philnext它是
C:\Projects\Shared\somefile.pas
。指示一个文件夹,该文件夹将从基本(或根)路径。
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;
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;