디렉터리를 수동으로 탐색하고 C # /. NET에서 크기를 계산하는 다음 루틴을 작성했습니다.
protected static float CalculateFolderSize(string folder)
{
float folderSize = 0.0f;
try
{
//Checks if the path is valid or not
if (!Directory.Exists(folder))
return folderSize;
else
{
try
{
foreach (string file in Directory.GetFiles(folder))
{
if (File.Exists(file))
{
FileInfo finfo = new FileInfo(file);
folderSize += finfo.Length;
}
}
foreach (string dir in Directory.GetDirectories(folder))
folderSize += CalculateFolderSize(dir);
}
catch (NotSupportedException e)
{
Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
}
}
}
catch (UnauthorizedAccessException e)
{
Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
}
return folderSize;
}
많은 수의 폴더에 대해이 루틴을 반복적으로 실행하는 응용 프로그램이 있습니다. .NET으로 폴더 크기를 계산하는 더 효율적인 방법이 있는지 궁금합니다. 프레임 워크에서 구체적인 내용을 보지 못했습니다. P / Invoke와 Win32 API를 사용해야합니까? .NET에서 폴더 크기를 계산하는 가장 효율적인 방법은 무엇입니까?
답변
나는 이것에 대해 고칠 수 있지만 디렉토리가 소비하는 공간을 계산하는 Win32 API가 있다고 생각하지 않습니다. 그렇다면 Explorer가 그것을 사용할 것이라고 가정합니다. 탐색기에서 큰 디렉터리의 속성을 얻는 경우 폴더 크기를 제공하는 데 걸리는 시간은 포함 된 파일 / 하위 디렉터리 수에 비례합니다.
당신의 일상은 상당히 깔끔하고 단순 해 보입니다. 디스크에서 사용되는 실제 공간이 아니라 파일 길이의 합계를 계산한다는 점에 유의하십시오. 클러스터, 파일 스트림 등의 끝에서 낭비 된 공간이 사용하는 공간은 무시됩니다.
답변
아니요, 이는 아래에 포함 된 관련 방법 인 디렉터리 크기를 계산 하는 권장 방법 과 같습니다.
public static long DirSize(DirectoryInfo d)
{
long size = 0;
// Add file sizes.
FileInfo[] fis = d.GetFiles();
foreach (FileInfo fi in fis)
{
size += fi.Length;
}
// Add subdirectory sizes.
DirectoryInfo[] dis = d.GetDirectories();
foreach (DirectoryInfo di in dis)
{
size += DirSize(di);
}
return size;
}
루트를 사용하여 다음과 같이 호출합니다.
Console.WriteLine("The size is {0} bytes.", DirSize(new DirectoryInfo(targetFolder));
… targetFolder
계산할 폴더 크기는 어디 입니까?
답변
DirectoryInfo dirInfo = new DirectoryInfo(@strDirPath);
long dirSize = await Task.Run(() => dirInfo.EnumerateFiles( "*", SearchOption.AllDirectories).Sum(file => file.Length));
답변
public static long DirSize(DirectoryInfo dir)
{
return dir.GetFiles().Sum(fi => fi.Length) +
dir.GetDirectories().Sum(di => DirSize(di));
}
답변
진짜 질문은 무엇을 위해 크기를 사용할 계획 입니까?
귀하의 첫 번째 문제가 있다는 것입니다 적어도 네 “파일 크기”에 대한 정의 :
-
파일의 처음부터 끝까지 이동하기 위해 건너 뛰어야하는 바이트 수인 “파일 끝”오프셋입니다.
즉, 파일의 논리적 바이트 수입니다 (사용 측면에서). -
실제로 저장되지 않은 첫 번째 바이트의 오프셋과 동일한 “유효한 데이터 길이” 입니다.
이것은 항상 “파일 끝”보다 작거나 같으며 클러스터 크기의 배수입니다.
예를 들어 1GB 파일은 1MB의 유효한 데이터 길이를 가질 수 있습니다. Windows에 처음 8MB를 읽도록 요청하면 처음 1MB를 읽고 나머지 데이터가있는 것으로 간주하여 0으로 반환합니다. -
파일의 “할당 된 크기”. 이것은 항상 “파일 끝”보다 크거나 같습니다.
OS가 파일에 할당 한 클러스터 수에 클러스터 크기를 곱한 값입니다.
“파일의 끝”은 “유효한 데이터 길이”보다 큰 경우와는 달리, 초과 바이트되어 있지 OS가 있도록, 파일의 데이터의 일부로 간주 하지 당신이 읽으려고하면 제로와 버퍼를 채우기 파일 끝을 넘어 할당 된 영역. -
압축 된 (및 스파 스?) 파일에만 유효한 파일의 “압축 된 크기”입니다. 이 파일에 실제로 할당 된
볼륨의 클러스터 수를 곱한 클러스터 크기와 같습니다.
비 압축 및 비 희소 파일의 경우 “압축 된 크기”라는 개념이 없습니다. 대신 “할당 된 크기”를 사용합니다.
당신의 두 번째 문제는 같은 “파일”는 것입니다 C:\Foo
실제로 여러 가질 수 스트림 데이터를.
이 이름은 기본 스트림을 나타냅니다 . 파일에는 과 같은 대체 스트림 이있을 수 있으며 C:\Foo:Bar
그 크기는 탐색기에도 표시되지 않습니다!
귀하의 세 번째 문제는 “파일이”할 수 있다는 것입니다 여러 이름이 ( “하드 링크를”).
예를 들어, C:\Windows\notepad.exe
그리고 C:\Windows\System32\notepad.exe
두 가지 이름 에 대한 동일한 파일. 모든 이름을 사용 하여 파일의 모든 스트림 을 열 수 있습니다 .
네 번째 문제는 “파일”(또는 디렉토리)이 실제로 파일 (또는 디렉토리)
이 아닐 수도 있다는 것입니다. 다른 파일 ( “기호 링크”또는 “재분석 지점”)에 대한 소프트 링크 일 수 있습니다. 또는 디렉토리).
다른 파일은 같은 드라이브에 있지 않을 수도 있습니다. 네트워크상의 무언가를 가리킬 수도 있고 재귀적일 수도 있습니다! 재귀적인 경우 크기는 무한대 여야합니까?
귀하의 다섯 번째는 특정 파일을 만들거나 디렉토리가 “필터”드라이버 있다는 것입니다 보면 그렇지 않은 경우에도 실제 파일이나 디렉토리와 같은가. 예를 들어, Microsoft의 WIM 이미지 파일 (압축 된)은 ImageX라는 도구를 사용하여 폴더에 “마운트”할 수 있으며 재분석 지점이나 링크처럼 보이지 않습니다 . 그것들은 실제로 디렉토리가 아니라는 점을 제외하고는 디렉토리와 똑같습니다. 그리고 “크기”라는 개념이 실제로 의미가 없습니다.
귀하의 여섯 번째 문제는 모든 파일에 메타 데이터를 필요로한다는 것이다.
예를 들어 동일한 파일에 대해 이름이 10 개 있으면 메타 데이터가 더 많이 필요하므로 공간이 필요합니다. 파일 이름이 짧으면 10 개의 이름을 갖는 것이 1 개의 이름을 갖는 것만 큼 저렴할 수 있으며, 길이가 길면 이름이 여러 개인 경우 메타 데이터에 더 많은 디스크 공간 을 사용할 수 있습니다 . (여러 스트림이있는 같은 이야기 등)
이것도 계산합니까?
답변
var size = new DirectoryInfo("E:\\").GetDirectorySize();
이 확장 메서드 뒤에있는 코드는 다음과 같습니다.
public static long GetDirectorySize(this System.IO.DirectoryInfo directoryInfo, bool recursive = true)
{
var startDirectorySize = default(long);
if (directoryInfo == null || !directoryInfo.Exists)
return startDirectorySize; //Return 0 while Directory does not exist.
//Add size of files in the Current Directory to main size.
foreach (var fileInfo in directoryInfo.GetFiles())
System.Threading.Interlocked.Add(ref startDirectorySize, fileInfo.Length);
if (recursive) //Loop on Sub Direcotries in the Current Directory and Calculate it's files size.
System.Threading.Tasks.Parallel.ForEach(directoryInfo.GetDirectories(), (subDirectory) =>
System.Threading.Interlocked.Add(ref startDirectorySize, GetDirectorySize(subDirectory, recursive)));
return startDirectorySize; //Return full Size of this Directory.
}
답변
다음 방법은 재귀 함수보다 더 빠르게 작업을 수행하는 것으로 보입니다.
long size = 0;
DirectoryInfo dir = new DirectoryInfo(folder);
foreach (FileInfo fi in dir.GetFiles("*.*", SearchOption.AllDirectories))
{
size += fi.Length;
}
간단한 콘솔 애플리케이션 테스트는이 루프가 재귀 함수보다 파일을 더 빠르게 합산하고 동일한 결과를 제공함을 보여줍니다. 이 코드를 단축하기 위해 Sum ()과 같은 LINQ 메서드를 사용하고 싶을 것입니다.