在Delphi文件类中获取文件大小或位置时是否应抛出异常?
关于Delphi文件处理类中GetSize/GetPosition属性的异常处理建议
这两个Win32 API确实可能触发错误,比如文件句柄无效、文件被其他进程关闭、权限不足等场景,因此必须在属性的获取方法中处理错误并抛出异常——否则调用者无法区分返回的$FFFFFFFF是真实的文件大小/位置,还是错误导致的无效值,会引发逻辑混乱。
错误判断逻辑修正
你的现有代码仅处理了“返回值为无效标记但实际是合法值”的场景,完全遗漏了真正的错误分支。正确的处理流程应为:
- 调用API获取返回值
- 检查返回值是否为对应API的无效标记
- 若为无效标记,调用
GetLastError:- 若返回值不是
NO_ERROR,说明发生错误,抛出异常 - 若返回值是
NO_ERROR,说明文件大小/位置确实为$FFFFFFFF
- 若返回值不是
- 若返回值有效,正常计算并返回结果
修正后的代码示例
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
相关产品推荐
相关产品推荐

