Получить размер файла на диске

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

Это дает логический размер файла, а не размер на диске.

Я хочу получить размер файла на диске в C # (желательно без взаимодействия ), как сообщается в Проводнике Windows.

Он должен давать правильный размер, в том числе для:

  • Сжатый файл
  • Редкий файл
  • Фрагментированный файл

Это использует GetCompressedFileSize, как было предложено ho1, а также GetDiskFreeSpace, как предложил PaulStack, однако он использует P / Invoke. Я тестировал его только для сжатых файлов, и я подозреваю, что он не работает для fragmentированных файлов.

  public static long GetFileSizeOnDisk(string 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); 

Приведенный выше код не работает должным образом в системах под управлением Windows Server 2008 или 2008 R2 или Windows 7 и Windows Vista, так как размер кластера всегда равен нулю (GetDiskFreeSpaceW и GetDiskFreeSpace возвращают -1, даже если UAC отключен). Вот модифицированный код, который работает.

C #

 public static long GetFileSizeOnDisk(string 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 String) 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 String, _  lpFileSizeHigh As UInteger) _ As UInteger End Function 

Согласно социальным форумам MSDN:

Размер на диске должен быть суммой размера кластеров, которые хранят файл:
http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvcs/thread/85bf76ac-a254-41d4-a3d7-e7803c8d9bc3
Вам нужно окунуться в P / Invoke, чтобы найти размер кластера; GetDiskFreeSpace () возвращает его.

См. Раздел Как получить размер на диске файла на C # .

Но учтите, что это не сработает в NTFS, где включено сжатие.

Я думаю, это будет так:

 double ifileLength = (finfo.Length / 1048576); //return file size in MB .... 

Я все еще делаю некоторые тесты для этого, чтобы получить подтверждение.

Давайте будем гением компьютера.