You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Delphi文件类中获取文件大小或位置时是否应抛出异常?

关于Delphi文件处理类中GetSize/GetPosition属性的异常处理建议

这两个Win32 API确实可能触发错误,比如文件句柄无效、文件被其他进程关闭、权限不足等场景,因此必须在属性的获取方法中处理错误并抛出异常——否则调用者无法区分返回的$FFFFFFFF是真实的文件大小/位置,还是错误导致的无效值,会引发逻辑混乱。

错误判断逻辑修正

你的现有代码仅处理了“返回值为无效标记但实际是合法值”的场景,完全遗漏了真正的错误分支。正确的处理流程应为:

  1. 调用API获取返回值
  2. 检查返回值是否为对应API的无效标记
  3. 若为无效标记,调用GetLastError:
    • 若返回值不是NO_ERROR,说明发生错误,抛出异常
    • 若返回值是NO_ERROR,说明文件大小/位置确实为$FFFFFFFF
  4. 若返回值有效,正常计算并返回结果

修正后的代码示例

function TFile.GetSize: Int64;
var
  FileSizeHi, FileSizeLo: Cardinal;
  LastErr: DWORD;
begin
  FileSizeLo := GetFileSize(FHandle, @FileSizeHi);
  if FileSizeLo = INVALID_FILE_SIZE then
  begin
    LastErr := GetLastError;
    if LastErr <> NO_ERROR then
      raise EIOException.CreateFmt('获取文件大小失败,错误码: %d', [LastErr]);
    // 文件大小确实为4GB-1的合法场景
    Result := $FFFFFFFF;
  end
  else
    Result := Int64(FileSizeHi) shl 32 or FileSizeLo;
end;

function TFile.GetPosition: Int64;
var
  FilePosHi, FilePosLo: Cardinal;
  LastErr: DWORD;
begin
  FilePosHi := 0;
  // FILE_CURRENT模式下传0偏移,直接获取当前指针位置
  FilePosLo := SetFilePointer(FHandle, 0, @FilePosHi, FILE_CURRENT);
  if FilePosLo = INVALID_SET_FILE_POINTER then
  begin
    LastErr := GetLastError;
    if LastErr <> NO_ERROR then
      raise EIOException.CreateFmt('获取文件位置失败,错误码: %d', [LastErr]);
    // 当前指针位置确实为4GB-1的合法场景
    Result := $FFFFFFFF;
  end
  else
    Result := Int64(FilePosHi) shl 32 or FilePosLo;
end;

关键说明

  • 异常类型选择:使用Delphi内置的EIOException更贴合文件操作错误的语义,方便调用者统一捕获文件相关异常。
  • 错误码辅助调试:异常信息中携带Windows错误码,可快速定位具体问题(比如错误码2对应文件找不到,5对应权限不足)。

内容的提问来源于stack exchange,提问作者Wolf Western

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:05:24