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);
FileInfo.Directory.Root
어떤 종류의 파일 시스템 링크도 처리 할 수있는 것처럼 보이지 않습니다. 따라서 symlink / hardlinks / junction point 또는 NTFS가 제공하는 모든 것이없는 클래식 로컬 드라이브 문자에서만 작동합니다.
System.ComponentModel
및 System.Runtime.InteropServices
.
위의 코드 는 클러스터 크기가 항상 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
.First()
그것이 같은 IEnumerable
아닌 IEnumerable<T>
, 당신은 코드 첫 번째 전화 사용하려는 경우.Cast<object>()
MSDN 소셜 포럼에 따르면 :
디스크의 크기는 파일을 저장하는 클러스터 크기의 합계 여야합니다. 클러스터 크기를 찾으려면 P / Invoke 에
long sizeondisk = clustersize * ((filelength + clustersize - 1) / clustersize);
들어가야 합니다. 반환합니다.GetDiskFreeSpace()
C #에서 파일의 디스크 크기를 가져 오는 방법을 참조하세요 .
그러나 압축이 켜져 있는 NTFS 에서는 작동하지 않는다는 점에 유의하십시오 .
GetCompressedFileSize
보다는 다음과 같은 것을 사용하는 것이 좋습니다 filelength
.