[c#] 디스크의 파일 크기 가져 오기

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

이것은 디스크의 크기가 아닌 파일의 논리적 크기를 제공합니다.

Windows 탐색기에서보고 한대로 C # (바람직하게는 interop 없이 ) 의 디스크에있는 파일의 크기를 얻고 싶습니다 .

다음을 포함하여 올바른 크기를 제공해야합니다.

  • 압축 파일
  • 스파 스 파일
  • 조각난 파일



답변

이것은 ho1이 제안한대로 GetCompressedFileSize를 사용하고 PaulStack이 제안한대로 GetDiskFreeSpace를 사용하지만 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);


답변

위의 코드 는 클러스터 크기가 항상 0이기 때문에 Windows Server 2008 또는 2008 R2 또는 Windows 7 및 Windows Vista 기반 시스템 에서 제대로 작동하지 않습니다 ( UAC가 비활성화 된 경우에도 GetDiskFreeSpaceW 및 GetDiskFreeSpace는 -1을 반환 합니다.) 작동하는 수정 된 코드는 다음과 같습니다.

씨#

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 소셜 포럼에 따르면 :

디스크의 크기는 파일을 저장하는 클러스터 크기의 합계 여야합니다. 클러스터 크기를 찾으려면 P / Invoke
long sizeondisk = clustersize * ((filelength + clustersize - 1) / clustersize);

들어가야 합니다. 반환합니다.GetDiskFreeSpace()

C #에서 파일의 디스크 크기를 가져 오는 방법을 참조하세요 .

그러나 압축이 켜져 있는 NTFS 에서는 작동하지 않는다는 점에 유의하십시오 .


답변

다음과 같을 것이라고 생각합니다.

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

확인을 받기 위해 아직 테스트 중입니다.


답변