FileGetDate工作了几次,想法?

时间:2013-10-12 20:45:17

标签: delphi delphi-5

有些文件可以使用,有些则没有。

var
  Src : integer;
  FileDate : LongInt;
begin
  Src:=FileOpen(SrcPath,fmOpenRead);
  FileDate:=FileGetDate(Src); // Crash here with FileDate = -1
  ...
  FileSetDate(Dest,FileDate);

我已检查过有效文件的属性,有些则没有,但它们是相同的。

“安全”相同。

“Src”是有效的Integer,适用于那些有效的和无效的。

我唯一能看到的是,那些没有的完整路径可以是130个字符或更长。但我改名为一些文件夹,并将其缩短为118,但仍然没有好处。

让我感到困惑。在一个2000+文件复制过程中,在这个FileGetDate的同一子文件夹崩溃中只有149个。

有什么建议吗?

由于

3 个答案:

答案 0 :(得分:2)

FileGetDate的调用返回-1。 documentation说明了这一点:

  

如果句柄无效,则返回值为-1。

换句话说,您对FileOpen的调用返回的句柄无效。您不检查代码中的任何错误。您的代码假设所有调用都成功。 FileOpen的失败模式是它返回-1。您没有检查FileOpen的返回值。您必须添加代码才能执行此操作。

请注意FileOpen的文档说:

  

注意:我们不鼓励使用非本地Delphi语言文件处理程序,如FileOpen。这些例程映射到系统   例程和返回OS文件句柄,而不是普通的Delphi文件变量。   这些是低级文件访问例程。用于普通文件操作   请改用AssignFile,Rewrite和Reset。

因此,即使是古老的传统Pascal I / O也优先于FileOpen

坦率地说,如果您想使用文件并获得有意义的错误诊断,则应使用Win32 API。致电CreateFile,如果失败,请检查GetLastError以找出原因。有很多方法可以使文件打开请求失败,而且实际上只有你可以找出文件的原因。我们手边没有文件,只有你这样做。

最后,您说您正在编写文件复制例程。系统已经提供了这样的东西,你最好不要使用它。你正在花费大量精力重新发明轮子。更重要的是,编写好的文件复制功能很难。已知系统提供的那个可以工作。你的版本可能会低劣。

要复制单个文件,您可以使用CopyFileCopyGFileEx。但是您要复制多个文件,而SHFileOperation就是API。

答案 1 :(得分:0)

3个想法,

首先是其他东西对该文件具有独占访问权限,而您无论如何都无法打开它。检查您打开的文件句柄是否有效。

第二种情况是,某些文件上可能有非常损坏的时间戳。我不知道它是怎么发生的,我只是知道它确实发生了。

最后,根据Linux上的文档,-1是一个有效的日期值,你没有提到你的源文件存储在哪个文件系统。

答案 2 :(得分:0)

以下是Delphi 5中FileGetDate()的实现:

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 在任何给定输入文件句柄上可能发生的不同故障点:

  1. GetFileTime()失败了吗?

  2. FileTimeToLocalFileTime()失败了吗?

  3. FileTimeToDosDateTime()失败了吗?

  4. 除非FileOpen()失败(你没有检查它 - 如果它无法打开文件,它会返回-1),那么#1或#不太可能(但不是不可能) 2失败了。但#3确实有一个记录的警告:

      

    MS-DOS日期格式只能代表1980年1月1日到12月31日之间的日期;如果输入文件时间超出此范围,则此转换将失败。

    在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);
    
    如果输入参数为false,则

    Win32Check()调用RaiseLastWin32Error()RaiseLastWin32Error()引发EOSError异常,其中包含ErrorCode属性中的实际错误代码。

    如果FileGetDate()失败,显然你不知道哪个Win32功能实际上失败了。这就是调试器发挥作用的地方。在项目选项中启用调试DCU,以允许您进入VCL / RTL源代码。查找失败的文件,在其上调用FileGetDate(),并逐步查看其源代码,看看这三个API函数实际上是否失败。

    同样适用于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()失败,那是因为:

    1. DosDateTimeToFileTime()失败了?

    2. LocalFileTimeToFileTime()失败了?

    3. SetFileTime()失败了吗?