如何从文本文件变量中获取完整文件名?

How to get the full file name from a TextFile variable?

以下代码写入名为 test.txt 的文件(在本例中,在当前目录中)

var
    F : TextFile;
begin
    AssignFile(F, 'test.txt');
    try
        Rewrite(F);
        //...
    finally
        CloseFile(F);
    end;
end;

如何从 F : TextFile 变量中提取完整的文件名?

您可以使用:

TTextRec(F).Name

从 TextFile 变量中提取 ASSIGN 的文件名(上例中的'test.txt')。

如果 "full file name" 你的意思是你想要它包括完整目录,你需要告诉我们你想要哪个版本的 Delphi,因为更现代的版本有很多这方面的功能是早期版本所没有的。

解决这个问题有两个步骤:

  1. 获取TextFile对象后面的文件句柄。
  2. 从该句柄中获取文件名。

对于第 1 步,您使用

var
  FileHandle: THandle;
....
FileHandle := TTextRec(F).Handle;

对于第 2 步,MSDN 上概述了该过程:Obtaining a File Name From a File Handle

由于 OP 似乎要求我最初理解的其他内容,因此我有以下答案:

{$J+}

USES Windows;

{$IFDEF UNICODE }
FUNCTION FileHandleToFileName(Handle : THandle) : STRING;
  BEGIN
    SetLength(Result,MAX_PATH+1);
    TRY
      SetLength(Result,GetFinalPathNameByHandle(Handle,@Result[LOW(Result)],LENGTH(Result),FILE_NAME_NORMALIZED))
    EXCEPT
      ON E:EExternalException DO SetLength(Result,0) ELSE RAISE
    END;
    IF COPY(Result,1,4)='\?\' THEN DELETE(Result,1,4)
  END;
{$ELSE }
CONST FILE_NAME_NORMALIZED = [=10=]000000;

FUNCTION GetFinalPathNameByHandleUndefined(hFile : THandle ; lpszFilePath : PChar ; cchFilePath,dwFlags : DWORD) : DWORD; stdcall;
  BEGIN
    StrPCopy(lpszFilePath,'');
    Result:=0
  END;

FUNCTION FileHandleToFileName(Handle : THandle) : STRING;
  TYPE
    TGetFinalPathNameByHandle   = FUNCTION(hFile : THandle ; lpszFilePath : PChar ; cchFilePath,dwFlags : DWORD) : DWORD; stdcall;

  CONST
    GetFinalPathNameByHandle    : TGetFinalPathNameByHandle = NIL;

  VAR
    Err                         : Cardinal;

  BEGIN
    IF NOT Assigned(GetFinalPathNameByHandle) THEN BEGIN
      GetFinalPathNameByHandle:=GetProcAddress(GetModuleHandle('kernel32'),'GetFinalPathNameByHandleA');
      IF NOT Assigned(GetFinalPathNameByHandle) THEN GetFinalPathNameByHandle:=GetFinalPathNameByHandleUndefined
    END;
    SetLength(Result,MAX_PATH+1);
    SetLength(Result,GetFinalPathNameByHandle(Handle,@Result[1],LENGTH(Result),FILE_NAME_NORMALIZED));
    IF COPY(Result,1,4)='\?\' THEN DELETE(Result,1,4)
  END;
{$ENDIF }

FUNCTION FileNameOf(VAR TXT : TextFile) : STRING;
  VAR
    Handle      : THandle;

  BEGIN
    Handle:=TTextRec(TXT).Handle;
    Result:=FileHandleToFileName(Handle);
    IF Result='' THEN Result:=StrPas(TTextRec(TXT).Name)
  END;

我目前使用 UNICODE 定义来确定 Delphi 是否已经有 GetFinalPathNameByHandle 的导入定义 - 如果我发现哪个版本实际实现了这个定义,它可能会被微调。

另请注意,GetFinalPathNameByHandle 仅对 Windows Vista 及更高版本有效。如果尝试在以前的版本上 运行,它将回退到简单地提取已分配的文件名。如果您需要对 pre-Vista 的支持,您可以查看 David 链接到的页面以获得适用于早期版本的版本。