ver tamaño reparar rapido programa para explorador carpetas carpeta archivos analizar acceso c# .net filesystems

c# - reparar - ¿Cuál es la forma más rápida de calcular el tamaño de las carpetas de Windows?



ver tamaño de carpetas windows cmd (9)

Agregue una referencia a Microsoft Scripting Runtime y use:

Scripting.FileSystemObject fso = new Scripting.FileSystemObject(); Scripting.Folder folder = fso.GetFolder([folder path]); Int64 dirSize = (Int64)folder.Size;

Si solo necesitas el tamaño, esto es mucho más rápido que recurrente.

Necesito calcular el tamaño de cientos de carpetas, algunas serán de 10 MB, quizás 10 GB, necesito una forma súper rápida de obtener el tamaño de cada carpeta usando C #.

Mi resultado final será:

Folder1 10.5GB

Carpeta2 230MB

Folder3 1.2GB

...


El enfoque más rápido en el marco 4.0-4.5 que pude encontrar para calcular el tamaño de los archivos y su cuenta en el disco fue:

using System.IO; using System.Threading; using System.Threading.Tasks; class FileCounter { private readonly int _clusterSize; private long _filesCount; private long _size; private long _diskSize; public void Count(string rootPath) { // Enumerate files (without real execution of course) var filesEnumerated = new DirectoryInfo(rootPath) .EnumerateFiles("*", SearchOption.AllDirectories); // Do in parallel Parallel.ForEach(filesEnumerated, GetFileSize); } /// <summary> /// Get real file size and add to total /// </summary> /// <param name="fileInfo">File information</param> private void GetFileSize(FileInfo fileInfo) { Interlocked.Increment(ref _filesCount); Interlocked.Add(ref _size, fileInfo.Length); } } var fcount = new FileCounter("F://temp"); fcount.Count();

Este enfoque apareció para mí como el mejor que pude encontrar en la plataforma .net. Por cierto, si necesita calcular el tamaño del clúster y el tamaño real en el disco, puede hacer lo siguiente:

using System.Runtime.InteropServices; private long WrapToClusterSize(long originalSize) { return ((originalSize + _clusterSize - 1) / _clusterSize) * _clusterSize; } private static int GetClusterSize(string rootPath) { int sectorsPerCluster = 0, bytesPerSector = 0, numFreeClusters = 0, totalNumClusters = 0; if (!GetDiskFreeSpace(rootPath, ref sectorsPerCluster, ref bytesPerSector, ref numFreeClusters, ref totalNumClusters)) { // Satisfies rule CallGetLastErrorImmediatelyAfterPInvoke. // see http://msdn.microsoft.com/en-us/library/ms182199(v=vs.80).aspx var lastError = Marshal.GetLastWin32Error(); throw new Exception(string.Format("Error code {0}", lastError)); } return sectorsPerCluster * bytesPerSector; } [DllImport(Kernel32DllImport, SetLastError = true)] private static extern bool GetDiskFreeSpace( string rootPath, ref int sectorsPerCluster, ref int bytesPerSector, ref int numFreeClusters, ref int totalNumClusters);

Y, por supuesto, debe volver a escribir GetFileSize () en la primera sección de código:

private long _diskSize; private void GetFileSize(FileInfo fileInfo) { Interlocked.Increment(ref _filesCount); Interlocked.Add(ref _size, fileInfo.Length); Interlocked.Add(ref _diskSize, WrapToClusterSize(fileInfo.Length)); }


Estoy bastante seguro de que esto será lento como el infierno, pero lo escribiría así:

using System.IO; long GetDirSize(string dir) { return new DirectoryInfo(dir) .GetFiles("", SearchOption.AllDirectories) .Sum(p => p.Length); }


Hay algunas pistas en este enlace (aunque está en Python) de una persona que se encuentra con problemas de rendimiento similares. Puede intentar llamar a la API de Win32 para ver si mejora el rendimiento, pero al final se encontrará con el mismo problema: una tarea solo se puede hacer tan rápido y si tiene que hacerlo muchas veces. Tomará mucho tiempo. ¿Puedes dar más detalles sobre para qué estás haciendo esto? Podría ayudar a las personas a crear una heurística o algunos trucos para ayudarte. Si estás haciendo mucho este cálculo, ¿estás guardando los resultados?


No hay una manera simple de hacer esto en .Net; Tendrás que recorrer cada archivo y subdirectorio. Vea los ejemplos here para ver cómo se hace.


Ok, esto es terrible, pero ...

Use un archivo por lotes recursivo de dos veces llamado dirsize.bat:

@ECHO OFF IF %1x==x GOTO start IF %1x==DODIRx GOTO dodir SET CURDIR=%1 FOR /F "usebackq delims=" %%A IN (`%0 DODIR`) DO SET ANSWER=%%A %CURDIR% ECHO %ANSWER% GOTO end :start FOR /D %%D IN (*.*) DO CALL %0 "%%D" GOTO end :dodir DIR /S/-C %CURDIR% | FIND "File(s)" GOTO end :end

Nota: debe haber un carácter de tabulación después del "%% A" final en la línea 5, no espacios.

Estos son los datos que estás buscando. Hará miles de archivos con bastante rapidez. De hecho, hace todo mi disco duro en menos de 2 segundos.

Ejecutar el archivo como este dirsize | sort /R /+25 dirsize | sort /R /+25 para ver el directorio más grande primero.

Buena suerte.


Puede hacer algo como esto, pero no hay una configuración rápida = verdadera cuando se trata de obtener tamaños de carpeta, tiene que sumar los tamaños de archivo.

private static IDictionary<string, long> folderSizes; public static long GetDirectorySize(string dirName) { // use memoization to keep from doing unnecessary work if (folderSizes.ContainsKey(dirName)) { return folderSizes[dirName]; } string[] a = Directory.GetFiles(dirName, "*.*"); long b = 0; foreach (string name in a) { FileInfo info = new FileInfo(name); b += info.Length; } // recurse on all the directories in current directory foreach (string d in Directory.GetDirectories(dirName)) { b += GetDirectorySize(d); } folderSizes[dirName] = b; return b; } static void Main(string[] args) { folderSizes = new Dictionary<string, long>(); GetDirectorySize(@"c:/StartingFolder"); foreach (string key in folderSizes.Keys) { Console.WriteLine("dirName = " + key + " dirSize = " + folderSizes[key]); } // now folderSizes will contain a key for each directory (starting // at c:/StartingFolder and including all subdirectories), and // the dictionary value will be the folder size }


Si hace clic con el botón derecho en un directorio grande, entonces las propiedades pueden ver que lleva mucho tiempo calcular el tamaño ... No creo que podamos superar a MS en esto. Una cosa que podría hacer es indexar los tamaños de los directorios / subdirectorios, si va a calcularlos una y otra vez ... eso aumentaría significativamente la velocidad.

Podría usar algo como esto para calcular el tamaño del directorio en C # recursivamente

static long DirSize(DirectoryInfo directory) { long size = 0; FileInfo[] files = directory.GetFiles(); foreach (FileInfo file in files) { size += file.Length; } DirectoryInfo[] dirs = directory.GetDirectories(); foreach (DirectoryInfo dir in dirs) { size += DirSize(dir); } return size; }


Dot Net Pearls tiene un método similar a los descritos aquí. Es sorprendente que la clase System.IO.DirectoryInfo no tenga un método para hacerlo, ya que parece ser una necesidad común y probablemente sería más rápido hacerlo sin hacer una transición nativa / administrada en cada objeto del sistema de archivos. Creo que si la clave es la velocidad, escribir un objeto no administrado para hacer este cálculo y luego invocarlo una vez por directorio desde el código administrado.