Récupère la taille du fichier sur le disque

var length = new System.IO.FileInfo(path).Length; 

Cela donne la taille logique du fichier, pas la taille du disque.

Je souhaite obtenir la taille d’un fichier sur le disque en C # (de préférence sans interopérabilité ) comme cela serait signalé par l’explorateur Windows.

Il devrait donner la bonne taille, y compris pour:

  • Un fichier compressé
  • Un fichier épars
  • Un fichier fragmenté

Cela utilise GetCompressedFileSize, comme suggéré par ho1, ainsi que GetDiskFreeSpace, comme suggéré par PaulStack, il utilise cependant P / Invoke. Je l’ai testé uniquement pour les fichiers compressés, et je soupçonne que cela ne fonctionne pas pour les fichiers fragmentés.

  public static long GetFileSizeOnDisk(ssortingng file) { FileInfo info = new FileInfo(file); uint dummy, sectorsPerCluster, bytesPerSector; int result = GetDiskFreeSpaceW(info.Directory.Root.FullName, out sectorsPerCluster, out bytesPerSector, out dummy, out dummy); if (result == 0) throw new Win32Exception(); uint clusterSize = sectorsPerCluster * bytesPerSector; uint hosize; uint losize = GetCompressedFileSizeW(file, out hosize); long size; size = (long)hosize << 32 | losize; return ((size + clusterSize - 1) / clusterSize) * clusterSize; } [DllImport("kernel32.dll")] static extern uint GetCompressedFileSizeW([In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName, [Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh); [DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)] static extern int GetDiskFreeSpaceW([In, MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName, out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters, out uint lpTotalNumberOfClusters); 

Le code ci-dessus ne fonctionne pas correctement sur les systèmes Windows Server 2008 ou 2008 R2 ou Windows 7 et Windows Vista car la taille de cluster est toujours égale à zéro (GetDiskFreeSpaceW et GetDiskFreeSpace return -1 même avec UAC désactivé). Voici le code modifié qui fonctionne.

C #

 public static long GetFileSizeOnDisk(ssortingng file) { FileInfo info = new FileInfo(file); uint clusterSize; using(var searcher = new ManagementObjectSearcher("select BlockSize,NumberOfBlocks from Win32_Volume WHERE DriveLetter = '" + info.Directory.Root.FullName.TrimEnd('\\') + "'") { clusterSize = (uint)(((ManagementObject)(searcher.Get().First()))["BlockSize"]); } uint hosize; uint losize = GetCompressedFileSizeW(file, out hosize); long size; size = (long)hosize << 32 | losize; return ((size + clusterSize - 1) / clusterSize) * clusterSize; } [DllImport("kernel32.dll")] static extern uint GetCompressedFileSizeW( [In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName, [Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh); 

VB.NET

  Private Function GetFileSizeOnDisk(file As Ssortingng) As Decimal Dim info As New FileInfo(file) Dim blockSize As UInt64 = 0 Dim clusterSize As UInteger Dim searcher As New ManagementObjectSearcher( _ "select BlockSize,NumberOfBlocks from Win32_Volume WHERE DriveLetter = '" + _ info.Directory.Root.FullName.TrimEnd("\") + _ "'") For Each vi As ManagementObject In searcher.[Get]() blockSize = vi("BlockSize") Exit For Next searcher.Dispose() clusterSize = blockSize Dim hosize As UInteger Dim losize As UInteger = GetCompressedFileSizeW(file, hosize) Dim size As Long size = CLng(hosize) << 32 Or losize Dim bytes As Decimal = ((size + clusterSize - 1) / clusterSize) * clusterSize Return CDec(bytes) / 1024 End Function  _ Private Shared Function GetCompressedFileSizeW( _ <[In](), MarshalAs(UnmanagedType.LPWStr)> lpFileName As Ssortingng, _  lpFileSizeHigh As UInteger) _ As UInteger End Function