获取磁盘上文件的大小

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

这给出了文件的逻辑大小,而不是磁盘上的大小。

我希望得到在C#中的文件的大小(最好是没有interop )在Windows资源pipe理器报告。

它应该给予正确的大小,包括:

  • 压缩文件
  • 一个稀疏的文件
  • 碎片文件

这个使用GetCompressedFileSize,就像ho1build议的那样,还有GetDiskFreeSpace,就像PaulStack所说的那样,但是它使用了P / Invoke。 我已经testing了它只适用于压缩文件,我怀疑它不适用于零散的文件。

  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即使禁用UAC也会返回-1)。下面是修改后的代码。

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 <DllImport("kernel32.dll")> _ Private Shared Function GetCompressedFileSizeW( _ <[In](), MarshalAs(UnmanagedType.LPWStr)> lpFileName As String, _ <Out(), MarshalAs(UnmanagedType.U4)> 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 .... 

我仍然在做一些testing,以获得确认。