下面是FileGetDate()
Delphi 5 中的实现:
function FileGetDate(Handle: Integer): Integer;
var
FileTime, LocalFileTime: TFileTime;
begin
if GetFileTime(THandle(Handle), nil, nil, @FileTime) and
FileTimeToLocalFileTime(FileTime, LocalFileTime) and
FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi,
LongRec(Result).Lo) then Exit;
Result := -1;
end;
这是任何给定的输入文件句柄上可能发生的3 个不同的故障点:
GetFileTime()
失败了吗?
FileTimeToLocalFileTime()
失败了吗?
FileTimeToDosDateTime()
失败了吗?
除非FileOpen()
失败(您没有检查它 --1
如果它无法打开文件,它会返回),那么 #1 或 #2 不太可能(但并非不可能)失败。但是#3确实有一个记录在案的警告:
MS-DOS 日期格式只能表示 1/1/1980 和 12/31/2107 之间的日期;如果输入文件时间超出此范围,则此转换失败。
您不太可能遇到时间戳为 2108 年及以后的文件,但您肯定会遇到时间戳为 1979 年及更早的文件。
所有 4 个函数(计算CreateFile()
内部调用的函数FileOpen()
)都通过 报告错误代码GetLastError()
,因此您可以这样做:
var
Src : integer;
FileDate : LongInt;
begin
Src := FileOpen(SrcPath, fmOpenRead);
Win32Check(Src <> -1);
FileDate := FileGetDate(Src);
Win32Check(FileDate <> -1);
...
Win32Check(FileSetDate(Dest, FileDate) = 0);
Win32Check()
RaiseLastWin32Error()
如果输入参数为假,则调用。在其属性中RaiseLastWin32Error()
引发EOSError
包含实际错误代码的异常。ErrorCode
如果FileGetDate()
失败,显然你不会知道哪个 Win32 函数实际上失败了。这就是调试器发挥作用的地方。在您的项目选项中启用调试 DCU 以允许您单步执行 VCL/RTL 源代码。找到一个失败的文件,对其调用 FileGetDate(),并逐步查看其源代码,看看这三个 API 函数是否真的失败了。
同样 for FileSetDate()
,它也在内部调用 3 个 API 函数:
function FileSetDate(Handle: Integer; Age: Integer): Integer;
var
LocalFileTime, FileTime: TFileTime;
begin
Result := 0;
if DosDateTimeToFileTime(LongRec(Age).Hi, LongRec(Age).Lo, LocalFileTime) and
LocalFileTimeToFileTime(LocalFileTime, FileTime) and
SetFileTime(Handle, nil, nil, @FileTime) then Exit;
Result := GetLastError;
end;
如果FileSetDate()
失败,是不是因为:
DosDateTimeToFileTime()
失败的?
LocalFileTimeToFileTime()
失败的?
SetFileTime()
失败了吗?