डिस्क पर फ़ाइल का आकार प्राप्त करें


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

यह फ़ाइल का तार्किक आकार देता है, डिस्क पर आकार नहीं।

मैं डिस्क पर एक फ़ाइल का आकार C # में प्राप्त करना चाहता हूं (अधिमानतः इंटरोप के बिना ) जैसा कि विंडोज एक्सप्लोरर द्वारा रिपोर्ट किया जाएगा।

इसके लिए सही आकार देना चाहिए:

  • एक संपीड़ित फ़ाइल
  • एक विरल फ़ाइल
  • एक खंडित फाइल

जवाबों:


50

यह GetCompressedFileSize का उपयोग करता है, जैसा कि ho1 ने सुझाव दिया, साथ ही 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) नया Win32Exception (परिणाम) फेंकें;
साइमन

'If (result == 0)' बिट सही है (देखें msdn ), लेकिन आप सही हैं कि मैं गलत कंस्ट्रक्टर का उपयोग कर रहा हूं। मैं अब इसे ठीक कर दूंगा।
19

FileInfo.Directory.Rootऐसा नहीं लगता है कि यह किसी भी तरह के फाइल सिस्टम लिंक को संभाल सकता है। इसलिए यह केवल क्लासिक लोकल ड्राइव लेटर्स पर काम करता है, जिसमें कोई सिम्लिंक्स / हार्डलिंक / जंक्शन पॉइंट्स या NTFS जो भी ऑफर करना है।
ygoe

क्या कोई भी कृपया चरणबद्ध तरीके से स्पष्टीकरण दे सकता है, विभिन्न चरणों में क्या किया गया है? यह समझने में बहुत मददगार होगा कि यह वास्तव में कैसे काम करता है। धन्यवाद।
बापी

5
इस कोड को नामस्थान System.ComponentModelऔर की आवश्यकता है System.Runtime.InteropServices
केनी एविट

17

ऊपर दिया गया कोड Windows Server 2008 या 2008 R2 या Windows 7 और Windows Vista पर आधारित सिस्टम पर ठीक से काम नहीं करता है क्योंकि क्लस्टर आकार हमेशा शून्य (GetDiskFreeSpaceW और GetDiskFreeSpace वापसी -1 UAC विकलांगों के साथ भी होता है ।) यहाँ संशोधित किया गया है जो काम करता है।

सी#

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

इस कोड को काम करने के लिए System.Managment संदर्भ आवश्यक है। ऐसा प्रतीत होता है जैसे कि WMI को छोड़कर विंडोज (6.x संस्करण) पर क्लस्टर आकार प्राप्त करने का कोई मानक तरीका नहीं है। : |
स्टीव जॉन्सन

1
मैंने एक विस्टा x64 मशीन पर अपना कोड लिखा और अब 64-बिट और WOW64 मोड में W7 x64 मशीन पर इसका परीक्षण किया। ध्यान दें कि GetDiskFreeSpace सफलता पर नॉनज़रो को वापस करने वाला है ।
margnus1

1
मूल प्रश्न C #
शेन कोर्ट्रेल

4
यह कोड भी संकलन नहीं करता है (एक बंद कोष्ठक का उपयोग करने पर गायब है) और एक लाइनर सीखने के उद्देश्यों के लिए बहुत ही भयानक है
मिकेल वी।

1
इस कोड में एक संकलन मुद्दा भी है जब .First()यह अनुरोध करता है कि यह एक है IEnumerableऔर एक नहीं है IEnumerable<T>, यदि आप कोड का उपयोग करना चाहते हैं तो पहला कॉल करें.Cast<object>()
yoel halb

5

MSDN सामाजिक मंचों के अनुसार:

डिस्क पर आकार फ़ाइल को संग्रहीत करने वाले समूहों के आकार का योग होना चाहिए:
long sizeondisk = clustersize * ((filelength + clustersize - 1) / clustersize);
आपको क्लस्टर आकार खोजने के लिए P / Invoke में डुबकी लगाने की आवश्यकता होगी ; GetDiskFreeSpace()उसे लौटाता है।

देखें कि C # में किसी फ़ाइल की डिस्क पर आकार कैसे प्राप्त करें

लेकिन कृपया ध्यान दें कि यह NTFS में काम नहीं करेगा जहां संपीड़न चालू है।


2
मेरा सुझाव है कि संकुचित और / या विरल फ़ाइलों के लिए खाते के GetCompressedFileSizeबजाय कुछ का उपयोग करना चाहिए filelength
हंस ओल्सन

-1

मुझे लगता है कि यह इस तरह होगा:

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

इसकी पुष्टि के लिए मैं अभी भी कुछ परीक्षण कर रहा हूं।


7
यह फ़ाइल का आकार (फ़ाइल के भीतर बाइट्स की संख्या) है। वास्तविक हार्डवेयर के ब्लॉक आकार के आधार पर, एक फ़ाइल अधिक डिस्क स्थान का उपभोग कर सकती है। उदाहरण के लिए मेरे HDD पर 600byte की एक फाइल ने डिस्क पर 4kB का उपयोग किया है। तो यह उत्तर गलत है।
0xBADF00D
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.