获取磁盘上的文件大小

Wer*_*ght 83 .net c# filesize

var length = new System.IO.FileInfo(path).Length;
Run Code Online (Sandbox Code Playgroud)

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

我想在C#中获取磁盘上文件的大小(最好没有互操作),如Windows资源管理器所报告的那样.

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

  • 压缩文件
  • 稀疏文件
  • 碎片文件

mar*_*us1 46

这使用了GetCompressedFileSize,如ho1建议的那样,以及GetDiskFreeSpace,正如PaulStack建议的那样,它确实使用了P/Invoke.我只测试了它的压缩文件,我怀疑它不适用于碎片文件.

    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);
Run Code Online (Sandbox Code Playgroud)

  • 此代码需要名称空间`System.ComponentModel`和`System.Runtime.InteropServices`. (4认同)

Ste*_*son 17

上面的代码在Windows Server 2008或2008 R2或基于Windows 7和Windows Vista的系统上无法正常工作,因为群集大小始终为零(即使禁用了UAC, GetDiskFreeSpaceW和GetDiskFreeSpace也返回-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);
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 这段代码甚至没有编译(使用时缺少一个右括号),而且一个班轮对于学习目的而言非常糟糕 (4认同)

sta*_*k72 5

根据 MSDN 社交论坛:

磁盘上的大小应该是存储文件的簇大小的总和:
long sizeondisk = clustersize * ((filelength + clustersize - 1) / clustersize);
您需要深入P/Invoke来查找簇大小;GetDiskFreeSpace()返回它。

请参阅如何在 C# 中获取文件在磁盘上的大小

但请注意,这在打开压缩的NTFS中不起作用。

  • 我建议使用类似`GetCompressedFileSize` 而不是`filelength` 来解释压缩和/或稀疏文件。 (2认同)