Поскольку GetCompressedFileSize
возвращает фактический размер обоих обычных / сжатых / резервных файлов любого типа , вы можете положиться на эту функцию, чтобы вернуть File Size on Disk
(Проводник Windows отображает это значение в виде коэффициента размера кластера тома) и получает File Size
с помощью функции GetFileSize
.
Из документов MSDN о GetCompressedFileSize
:
Если файл не находится на томе, который поддерживает сжатие или разреженные файлы, или если файл не сжат или разреженный файл, полученное значение является фактическим размером файла, таким же, как значение, возвращаемоевызов GetFileSize.
Итак, логика описывается следующим кодом (проверено на Windows XP с файлами FAT32 / FAT / CDfs):
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;
Мы может проверить GetVolumeInformation
на сжатие / разреженную поддержку, а затем GetFileAttributes
для проверки на FILE_ATTRIBUTE_COMPRESSED
или FILE_ATTRIBUTE_SPARSE_FILE
, НО, поскольку GetCompressedFileSize
делает это для нас внутренне (позвонив по номеру NtQueryInformationFile
), Я не вижу смысла в этих тестах.