首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何查询“磁盘上的大小”文件信息?

如何查询“磁盘上的大小”文件信息?
EN

Stack Overflow用户
提问于 2012-03-28 08:24:36
回答 5查看 3.3K关注 0票数 7

我希望再现任何给定文件的Windows ->属性对话框->常规属性页中显示的行为。具体来说,我想要重现“磁盘上的大小”字段的确切值。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-03-28 16:07:58

正如其他人所说的,您需要使用GetFileInformationByHandleEx,但是看起来您需要使用FILE_STANDARD_INFOFILE_ID_BOTH_DIR_INFO。您想要的信息在每个目录的AllocationSize成员中返回,但第二个是目录句柄,用于列出目录内的文件,而不是目录本身(注意:不是递归的,只是顶层的)。为了使它更简单,FILE_STANDARD_INFO有一个Directory布尔值,所以如果您不确定,就先调用它。根据FILE_ID_BOTH_DIR_INFO的文档,

AllocationSize包含指定为文件分配多少空间(以字节为单位)的值。此值通常是基础物理设备扇区或群集大小的倍数。

这似乎为您提供了Size on Disk信息。

我还没有找到FILE_ID_BOTH_DIR_INFO结构的Delphi翻译。困难似乎是最终成员WCHAR FileName[1],它被描述为:

FileName1 包含文件名字符串的第一个字符。在内存中,后面跟着字符串的其余部分。

我不知道德尔菲会怎么处理这件事。

票数 3
EN

Stack Overflow用户

发布于 2012-03-28 16:53:00

陈雷蒙德关于Windows机密的文章描述了如何计算该值。最相关的段落是:

磁盘测量的尺寸要复杂得多。如果驱动器支持压缩(如Get卷信息函数返回的FILE_FILE_COMPRESSION标志所报告的那样),并且文件被压缩或稀疏(FILE_ATTRIBUTE_COMPRESSED,FILE_ATTRIBUTE_SPARSE_FILE),那么文件的磁盘大小就是Get压缩文件大小函数报告的值。这将报告文件的压缩大小(如果压缩的话)或文件的大小减去不提交和逻辑上处理为零的部分(如果稀疏的话)。如果文件既不是压缩的,也不是稀疏的,那么磁盘上的大小就是Find First file函数报告到最近的集群的文件大小。

票数 3
EN

Stack Overflow用户

发布于 2012-03-29 14:14:10

由于GetCompressedFileSize将返回任何卷类型的普通/压缩/备用文件的实际大小,因此可以依赖此函数返回File Size on Disk (Windows将此值显示为卷群集大小的因子),并使用GetFileSize函数获取File Size

从MSDN文档中获取有关GetCompressedFileSize的信息

如果文件不在支持压缩或稀疏文件的卷上,或者该文件未被压缩或稀疏文件,则获得的值为实际文件大小,与调用GetFileSize返回的值相同。

因此,下面的代码描述了逻辑(在Windows上使用FAT 32/FAT/CDfs文件进行了测试):

代码语言:javascript
运行
复制
procedure FileSizeEx(const FileName: string; out Size, SizeOnDisk: UINT);
var
  Drive: string;
  FileHandle: THandle;
  SectorsPerCluster,
  BytesPerSector,
  Dummy: DWORD;
  ClusterSize: DWORD;
  SizeHigh, SizeLow: DWORD;
begin
  Assert(FileExists(FileName));
  Drive := IncludeTrailingPathDelimiter(ExtractFileDrive(FileName));
  if not GetDiskFreeSpace(PChar(Drive), SectorsPerCluster, BytesPerSector, Dummy, Dummy) then
    RaiseLastOSError;

  ClusterSize := SectorsPerCluster * BytesPerSector;

  FileHandle := CreateFile(PChar(FileName), 0, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
    nil, OPEN_EXISTING, 0, 0);
  if (FileHandle = INVALID_HANDLE_VALUE) then
    RaiseLastOSError;
  try
    SizeLow := Windows.GetFileSize(FileHandle, @SizeHigh);
    if (GetLastError <> NO_ERROR) and (SizeLow = INVALID_FILE_SIZE) then
      RaiseLastOSError;
    Size := UINT(SizeHigh shl 32 or SizeLow);
  finally
    if (FileHandle <> INVALID_HANDLE_VALUE) then
      CloseHandle(FileHandle);
  end;

  SizeLow := GetCompressedFileSize(PChar(FileName), @SizeHigh);
  if (GetLastError <> NO_ERROR) and (SizeLow = INVALID_FILE_SIZE) then
    RaiseLastOSError;

  SizeOnDisk := UINT(SizeHigh shl 32 or SizeLow);
  if (SizeOnDisk mod ClusterSize) > 0 then
    SizeOnDisk := SizeOnDisk + ClusterSize - (SizeOnDisk mod ClusterSize);
end;

我们可以检查Get­Volume­Information的压缩/稀疏支持,然后检查GetFileAttributes来测试FILE_ATTRIBUTE_COMPRESSEDFILE_ATTRIBUTE_SPARSE_FILE,但是由于GetCompressedFileSize在内部(通过调用NtQueryInformationFile)进行测试,所以我认为这些测试没有意义。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9903679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档