Delphi Tpath.Combine ('c:', 'myfile.txt') excludes DirSeperator

So when I run

TPath.Combine('c:', 'myfile.txt');

      

in Delphi XE2 then I get "C: myfile.txt" instead. This is not what I expect, and it is not a valid path in windows. I would expect TPath.Combine to become a windows API call ( http://msdn.microsoft.com/en-us/library/fyy7a5kt%28v=vs.110%29.aspx ) or have the same behavior as API.

Is there something I am doing wrong? Can I "fix" TPath.Combine's behavior? Or do I have to search for all uses in my code and replace it with string concatenation with "\" in between?

+3


source to share


3 answers


I think the behavior is correct and how it was designed. There is a difference between C:myfile.txt

and C:\myfile.txt

. the windows documentation calls this explicitly:

If the filename begins with only a drive pointer, but not a backslash after the colon, it is interpreted as a relative path to the current directory on the drive with the specified letter. Note that the current directory may or may not be the root directory depending on which it was installed on during the last "change directory" operation on that drive. Examples of this format:

  • "C: tmp.txt" refers to a file named "tmp.txt" in the current directory on drive C.
  • "C: tempdir \ tmp.txt" refers to a file in a subdirectory of the current directory on drive C.

If the RTL function has TPath.Combine

added a separator after the drive pointer then you cannot use TPath.Combine

to create the path, eg "C:tmp.txt"

. So, if you want a directory separator, you need to supply it yourself:

TPath.Combine('c:\', 'myfile.txt');

      



Note that the framework.net framework method Path.Combine

, in which the Delphi RTL class is TPath

loosely modeled, behaves the same as the Delphi RTL equivalent.

Connected:

+8


source


When concatenating folder names and folder files, it is always useful to specify the feeder name using the IncludeTrailingPathDelimiter method. This method will add a trailing separator to your path if it doesn't exist



TPath.Combine(IncludeTrailingPathDelimiter('c:'), 'myfile.txt');

      

0


source


The Path.Combine and CombinePath functions have problems with very long path names, in addition, when the path is not physically on disk (but, for example, in a zip file), then it also does not work. This implementation works for me:

function ExpandFileNameEx(const BasePath, RelativeFileName: string): string;
var
  p:integer;
  s,folder:string;
begin
  { Check if Relative file name is a fully qualified path: }
  if (pos(':\', RelativeFileName) > 0) or (copy(RelativeFileName,1,2) = '\\') then
    Result := RelativeFileName

  { Check if Relative file name is a root path assignment: }
  else if copy(RelativeFileName,1,1) = '\' then
  begin
    Result := IncludeTrailingPathDelimiter(ExtractFileDrive(BasePath))
             + Copy(RelativeFileName,2,Length(RelativeFileName));
  end else
  begin
    { Check all sub paths in Relative file name: }
    Result := BasePath;
    s := RelativeFileName;
    repeat
      p := pos('\', s);
      if p > 0 then
      begin
        folder := Copy(s,1,p-1);
        Delete(s, 1,p);
      end else
      begin
        folder := s;
        s := '';
      end;

      if folder <> EmptyStr then
      begin
        if Folder = '..' then
          Result := ExtractFileDir(Result)
        else if Folder = '.' then
          { No action }
        else
          Result := IncludeTrailingPathDelimiter(Result) + Folder;
      end;
    until p = 0;
  end;
end;

      

0


source







All Articles