Quiero reproducir el comportamiento exhibido en el Windows Explorer -> cuadro de diálogo Propiedades -> General de propiedades para cualquier archivo dado. Específicamente quiero reproducir el valor exacto del campo "Tamaño en el disco".¿Cómo consulto la información del archivo "Tamaño en el disco"?
Respuesta
Como han dicho otros, necesita usar GetFileInformationByHandleEx
, pero parece que necesita usar FILE_ID_BOTH_DIR_INFO. La información que desea se devuelve en el miembro AllocationSize
. De acuerdo con el enlace de arriba,
allocationSize Contiene el valor que especifica la cantidad de espacio asignado para el archivo, en bytes. Este valor generalmente es un múltiplo del tamaño del sector o clúster del dispositivo físico subyacente.
Esto parece darle la información Size on Disk
.
No he encontrado una traducción Delphi de la estructura FILE_ID_BOTH_DIR_INFO
. La dificultad parece ser el último miembro, WCHAR FileName[1]
, que se describe como:
Nombre de archivo [1]
Contiene el primer carácter de la cadena de nombre de archivo. Esto es seguido en memoria por el resto de la cadena.
No estoy seguro de cómo se manejaría esto en Delphi.
Vista + solo de acuerdo con los documentos. – kobik
En realidad, no. Hay una nota que dice que está disponible en XP, en la sección Archivo de encabezado: WinBase.h (incluye Windows.h); FileExtd.h en Windows Server 2003 y ** Windows XP **, con una biblioteca para vincular, por lo que podría crear una DLL contenedora en C++ Builder y luego llamarla a través de esa envoltura. –
O, de hecho, cualquier compilador C o C++, p.los compiladores de MS distribuidos en Platform SDK –
Usted puede utilizar la función GetFileInformationByHandleEx obtener FILE_COMPRESSION_INFO estructura, su campo CompressedFileSize
es el valor que necesita (igual que el devuelto por GetCompressedFileSize
).
Aunque ten en cuenta que usar esto en XP no es trivial –
Ahora estoy completamente perplejo. FILE_COMPRESSION_INFO devuelto de la llamada correcta se completa con todos los ceros. Sin embargo, finalmente descubrí qué es inusual con el archivo ofensivo, actualizando la pregunta. – OnTheFly
@ user539484: ¿y si pasas FILE_STANDARD_INFO y luego lees AllocationSize? Cuando eso falla, pruebe FILE_STREAM_INFO y lea StreamAllocationSize. Solo funciona en Vista y superior. –
Raymond Chen El artículo de Windows Confidential describe cómo se calcula ese valor. El párrafo más pertinente dice:
El tamaño en la medición del disco es más complicado. Si el disco admite compresión (como informa el indicador FILE_FILE_COMPRESSION devuelto por la función GetVolumeInformation) y el archivo está comprimido o disperso (FILE_ATTRIBUTE_COMPRESSED, FILE_ATTRIBUTE_SPARSE_FILE), entonces el tamaño en el disco de un archivo es el valor informado por la función GetCompressedFileSize. Esto informa el tamaño comprimido del archivo (si está comprimido) o el tamaño del archivo menos las partes que se eliminaron y se trataron lógicamente como cero (si es escaso). Si el archivo no está comprimido ni es escaso, entonces el Tamaño en el disco es el tamaño del archivo informado por la función FindFirstFile redondeado al clúster más cercano.
Publicando una rutina según el extracto de David del artículo de Raymond. ¡Siéntete libre de mejorarlo!
uses
System.SysUtils, Windows;
function GetClusterSize(Drive: String): integer;
var
SectorsPerCluster, BytesPerSector, dummy: Cardinal;
begin
SectorsPerCluster := 0;
BytesPerSector := 0;
GetDiskFreeSpace(PChar(Drive), SectorsPerCluster, BytesPerSector, dummy, dummy);
Result := SectorsPerCluster * BytesPerSector;
end;
function FindSizeOnDisk(Drive: String; AFilename: string): Int64;
var
VolumeSerialNumber: DWORD;
MaximumComponentLength: DWORD;
FileSystemFlags: DWORD;
HighSize: DWORD;
FRec: TSearchRec;
AClusterSize: integer;
AFileSize, n: Int64;
begin
Result := 0;
Drive := IncludeTrailingPathDelimiter(ExtractFileDrive(Drive));
GetVolumeInformation(PChar(Drive), nil, 0, @VolumeSerialNumber,
MaximumComponentLength, FileSystemFlags, nil, 0);
if ((FileSystemFlags AND FILE_FILE_COMPRESSION) <> 0) AND
((FileSystemFlags AND (FILE_VOLUME_IS_COMPRESSED OR
FILE_SUPPORTS_SPARSE_FILES)) <> 0) then
begin // Compressed or Sparse disk
Result := GetCompressedFileSize(PChar(AFilename), @HighSize);
// Not sure if this is correct on a sparse disk ??
end
else
begin
if (System.SysUtils.FindFirst(AFilename, faAnyFile, FRec) = 0) then
begin
AFileSize := FRec.Size;
AClusterSize := GetClusterSize(Drive);
n := AFileSize mod AClusterSize;
if n > 0 then // Round up to nearest cluster size
Result := AFileSize + (AClusterSize - n)
else
Result := AFileSize;
System.SysUtils.FindClose(FRec);
end;
end;
end;
Desde GetCompressedFileSize
volverá al tamaño real, tanto por la normalidad/comprimido/repuestos archivos de cualquier tipo volumen, se puede confiar en esta función para devolver el File Size on Disk
(Windows Explorer está mostrando este valor como factor de volumen Tamaño del clúster), y obtenga el File Size
utilizando la función GetFileSize
.
a partir de documentos de MSDN sobre GetCompressedFileSize
:
Si el archivo no se encuentra en un volumen que soporta compresión o archivos dispersos, o si el archivo no está comprimido o un archivo disperso, el valor obtenido es el tamaño del archivo real, el mismo que el valor devuelto mediante una llamada a GetFileSize.
Así que la lógica es descrito por el siguiente código (probado en Windows XP con archivos/FAT/CDFS FAT32):
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;
Nos podría comprobar el GetVolumeInformation
para la compresión/escasa soporte, y luego GetFileAttributes
para probar FILE_ATTRIBUTE_COMPRESSED
o FILE_ATTRIBUTE_SPARSE_FILE
, PERO dado que GetCompressedFileSize
lo hace internamente para nosotros (llamando a NtQueryInformationFile
), no veo sentido en estas pruebas .
- 1. Obtener el tamaño del archivo en el disco
- 2. ¿Cómo recupero la información del disco en C#?
- 3. ¿Cómo obtener información sobre el sistema de archivos del disco?
- 4. ¿Cómo se obtiene el archivo en el disco, y no solo el tamaño del archivo en Java?
- 5. ¿Cómo obtener información sobre el búfer/archivo actual en emacs?
- 6. ¿Cómo obtener el tamaño de archivo en el disco en Linux?
- 7. ¿Cómo optimizar el tamaño del archivo PDF?
- 8. Cómo representar visualmente el tamaño del archivo
- 9. ¿Cómo consulto la tabla ARP en iPhone?
- 10. Cómo obtener el tamaño del archivo HttpPostedFileBase
- 11. ¿Cómo obtener el tamaño real en disco de un archivo de PowerShell?
- 12. ¿Cómo consulto la dirección IP actual del iPhone?
- 13. ¿Cómo elimino un archivo del disco en IntelliJ IDEA?
- 14. Administrar tamaño del archivo .git
- 15. ¿Por qué el tamaño del mapa de bits es más grande en la memoria que en el disco en Android?
- 16. Determinación del tamaño del archivo en VB.NET
- 17. ¿Cómo cambiar el tamaño del botón del archivo de entrada?
- 18. ¿Cómo conseguir el tamaño del archivo en Java
- 19. Node.js: cómo limitar el tamaño de la solicitud HTTP y el tamaño del archivo de carga?
- 20. JQuery - Arrastrar y soltar archivos - ¿Cómo obtener información del archivo?
- 21. tamaño del archivo en Haskell
- 22. Cómo reducir el tamaño del archivo de audio en IOS
- 23. NSFileManager - Comprobar el tamaño del archivo?
- 24. ¿Cómo leo la información del sistema en C++?
- 25. ¿cómo obtengo el tamaño del archivo temporal en Android?
- 26. Cómo reducir el tamaño del archivo de imagen en java
- 27. ¿Cómo evitar la fragmentación del disco duro?
- 28. Tamaño del archivo cargado
- 29. ¿Cómo puedo obtener un archivo sin eliminarlo del disco?
- 30. ¿Cómo obtengo el comando find para imprimir el tamaño del archivo con el nombre del archivo?
¿Puede ampliar lo que quiere decir cuando dice que 'GetCompressedFileSize' no es la función correcta? –
@DavidHeffernan, quise aconsejar a un experto para que no entrara en el mismo pozo aparentemente obvio después de mí ... – OnTheFly
¿Estás seguro de que no funciona? Tal vez fallaste en combinar las DWORD bajas y altas correctamente. –