Używa GetCompressedFileSize, jak sugerował ho1, a także GetDiskFreeSpace, jak zasugerował PaulStack, jednak używa P / Invoke. Przetestowałem go tylko dla plików skompresowanych i podejrzewam, że nie działa dla plików pofragmentowanych.
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);
FileInfo.Directory.Root
nie wygląda na to, żeby mógł obsłużyć jakikolwiek rodzaj linków do systemu plików. Działa więc tylko na klasycznych literach dysków lokalnych bez dowiązań symbolicznych / twardych / punktów połączeń lub czegokolwiek, co ma do zaoferowania NTFS.System.ComponentModel
iSystem.Runtime.InteropServices
.Powyższy kod nie działa poprawnie w systemie Windows Server 2008 systemy R2 lub Windows 7 i Windows Vista opartych lub 2008 jako rozmiar klastra jest zawsze zero (GetDiskFreeSpaceW i GetDiskFreeSpace powrót -1 nawet z UAC wyłączone.) Oto zmodyfikowany kod, który działa.
DO#
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
źródło
.First()
ponieważ jest toIEnumerable
a nie anIEnumerable<T>
, jeśli chcesz użyć kodu pierwsze wywołanie.Cast<object>()
Według forów społecznościowych MSDN:
Zobacz, jak uzyskać rozmiar na dysku pliku w języku C # .
Należy jednak pamiętać o tym, że nie zadziała to w systemie plików NTFS, w którym włączona jest kompresja.
źródło
GetCompressedFileSize
raczej użycie czegoś takiego niżfilelength
uwzględnienie skompresowanych i / lub rzadkich plików.Myślę, że będzie tak:
double ifileLength = (finfo.Length / 1048576); //return file size in MB ....
Wciąż przeprowadzam testy, aby uzyskać potwierdzenie.
źródło