2010-07-08 25 views
5

necesito para calcular el tamaño del directorio en VB .Net¿Cuál es la mejor manera de calcular el tamaño de un directorio en VB .NET?

sé los siguientes 2 métodos

Método 1: desde MSDN http://msdn.microsoft.com/en-us/library/system.io.directory.aspx

'El siguiente ejemplo calcula el tamaño de un directorio ' y sus subdirectorios, si los hay, y muestra el tamaño total 'en bytes.

Imports System 
Imports System.IO 

Public Class ShowDirSize 

Public Shared Function DirSize(ByVal d As DirectoryInfo) As Long 
    Dim Size As Long = 0 
    ' Add file sizes. 
    Dim fis As FileInfo() = d.GetFiles() 
    Dim fi As FileInfo 
    For Each fi In fis 
     Size += fi.Length 
    Next fi 
    ' Add subdirectory sizes. 
    Dim dis As DirectoryInfo() = d.GetDirectories() 
    Dim di As DirectoryInfo 
    For Each di In dis 
     Size += DirSize(di) 
    Next di 
    Return Size 
End Function 'DirSize 

Public Shared Sub Main(ByVal args() As String) 
    If args.Length <> 1 Then 
     Console.WriteLine("You must provide a directory argument at the command line.") 
    Else 
     Dim d As New DirectoryInfo(args(0)) 
     Dim dsize As Long = DirSize(d) 
     Console.WriteLine("The size of {0} and its subdirectories is {1} bytes.", d, dsize) 
    End If 
End Sub 'Main 
End Class 'ShowDirSize 

Método 2: desde What's the best way to calculate the size of a directory in .NET?

Dim size As Int64 = (From strFile In My.Computer.FileSystem.GetFiles(strFolder, _ 
       FileIO.SearchOption.SearchAllSubDirectories) _ 
       Select New System.IO.FileInfo(strFile).Length).Sum() 

Ambos métodos funcionan bien. Sin embargo, toman mucho tiempo para calcular el tamaño del directorio si hay muchas subcarpetas. Por ejemplo, tengo un directorio con 150,000 subcarpetas. Los métodos anteriores tomaron alrededor de 1 hora y 30 minutos para calcular el tamaño del directorio. Sin embargo, si verifico el tamaño desde Windows tarda menos de un minuto.

Por favor sugiera maneras mejores y más rápidas de calcular el tamaño del directorio.

Respuesta

3

Though this answer is talking about Python, el concepto también se aplica aquí.

Explorador de Windows utiliza la API de llamadas al sistema FindFirstFile y FindNextFile de forma recursiva para extraer información de archivos y, a continuación, puede acceder a los archivos de tamaño muy rápidamente a través de los datos que se pasa de nuevo a través de un struct, WIN32_FIND_DATA: http://msdn.microsoft.com/en-us/library/aa365740(v=VS.85).aspx.

Mi sugerencia sería implementar estas llamadas API utilizando P/Invoke, y creo que experimentará un aumento significativo en el rendimiento.

5

Hacer el trabajo en paralelo debería hacerlo más rápido, al menos en máquinas con núcleos múltiples. Pruebe este código C#. Tendrá que traducir para VB.NET.

private static long DirSize(string sourceDir, bool recurse) 
{ 
    long size = 0; 
    string[] fileEntries = Directory.GetFiles(sourceDir); 

    foreach (string fileName in fileEntries) 
    { 
     Interlocked.Add(ref size, (new FileInfo(fileName)).Length); 
    } 

    if (recurse) 
    { 
     string[] subdirEntries = Directory.GetDirectories(sourceDir); 

     Parallel.For<long>(0, subdirEntries.Length,() => 0, (i, loop, subtotal) => 
     { 
      if ((File.GetAttributes(subdirEntries[i]) & FileAttributes.ReparsePoint) != FileAttributes.ReparsePoint) 
      { 
       subtotal += DirSize(subdirEntries[i], true); 
       return subtotal; 
      } 
      return 0; 
     }, 
      (x) => Interlocked.Add(ref size, x) 
     ); 
    } 
    return size; 
} 
2

Este es un fragmento de código corto y dulce que hará el trabajo. Sólo tiene que restablecer el contador antes de llamar a la función

Public Class Form1 
Dim TotalSize As Long = 0 
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 
    TotalSize = 0 'Reset the counter 
    Dim TheSize As Long = GetDirSize("C:\Test") 
    MsgBox(FormatNumber(TheSize, 0) & " Bytes" & vbCr & _ 
      FormatNumber(TheSize/1024, 1) & " Kilobytes" & vbCr & _ 
      FormatNumber(TheSize/1024/1024, 1) & " Megabytes" & vbCr & _ 
      FormatNumber(TheSize/1024/1024/1024, 1) & " Gigabytes") 
End Sub 
Public Function GetDirSize(RootFolder As String) As Long 
    Dim FolderInfo = New IO.DirectoryInfo(RootFolder) 
    For Each File In FolderInfo.GetFiles : TotalSize += File.Length 
    Next 
    For Each SubFolderInfo In FolderInfo.GetDirectories : GetDirSize(SubFolderInfo.FullName) 
    Next 
    Return TotalSize 
End Function 
End Class 
+0

@ Magicprog.fr, lazo agradable. ¿Me puede decir cuál es el truco con el contador de restablecimiento aquí? ¿Por qué todavía devuelve el tamaño de carpeta correcto con todas las subcarpetas? Simplemente no lo entiendo ... – LuckyLuke82

0

Código VB basado en la respuesta de Jamie:

Imports System.Threading 
Imports System.IO 

Public Function GetDirectorySize(ByVal path As String, Optional recurse As Boolean = False) As Long 
    Dim totalSize As Long = 0 
    Dim files() As String = Directory.GetFiles(path) 
    Parallel.For(0, files.Length, 
        Sub(index As Integer) 
        Dim fi As New FileInfo(files(index)) 
        Dim size As Long = fi.Length 
        Interlocked.Add(totalSize, size) 
        End Sub) 

    If recurse Then 
     Dim subDirs() As String = Directory.GetDirectories(path) 
     Dim subTotal As Long = 0 
     Parallel.For(0, subDirs.Length, 
         Function(index As Integer) 
         If (File.GetAttributes(subDirs(index)) And FileAttributes.ReparsePoint) <> FileAttributes.ReparsePoint Then 
          Interlocked.Add(subTotal, GetDirectorySize(subDirs(index), True)) 
          Return subTotal 
         End If 
         Return 0 
         End Function) 
     Interlocked.Add(totalSize, subTotal) 
    End If 

    Return totalSize 
End Function 
+0

No compila. 'Interlocked' undefined. – stigzler

+0

@stigzler está definido en System.Threading. Verifique la respuesta actualizada. – mathiasfk

0

Aquí esta tan corto como lo puedo conseguir.

Mostrará el tamaño del seleccionado en un cuadro de mensaje. Necesitará un FolderBrowserDialog en el formulario para que esto funcione.

Class Form1 

Private Sub form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    Try 
     If (FolderBrowserDialog1.ShowDialog() = DialogResult.OK) Then 
     Else : End 
     End If 
     Dim dInfo As New IO.DirectoryInfo(FolderBrowserDialog1.SelectedPath) 
     Dim sizeOfDir As Long = DirectorySize(dInfo, True) 
     MsgBox("Showing Directory size of " & FolderBrowserDialog1.SelectedPath _ 
       & vbNewLine & "Directory size in Bytes : " & "Bytes " & sizeOfDir _ 
       & vbNewLine & "Directory size in KB : " & "KB " & Math.Round(sizeOfDir/1024, 3) _ 
       & vbNewLine & "Directory size in MB : " & "MB " & Math.Round(sizeOfDir/(1024 * 1024), 3) _ 
       & vbNewLine & "Directory size in GB : " & "GB " & Math.Round(sizeOfDir/(1024 * 1024 * 1024), 3)) 
    Catch ex As Exception 
    End Try 
End Sub 

Private Function DirectorySize(ByVal dInfo As IO.DirectoryInfo, ByVal includeSubDir As Boolean) As Long 
    Dim totalSize As Long = dInfo.EnumerateFiles().Sum(Function(file) file.Length) 
    If includeSubDir Then totalSize += dInfo.EnumerateDirectories().Sum(Function(dir) DirectorySize(dir, True)) 
    Return totalSize 
End Function 

End Class 
0

Pruebe lo siguiente para obtener tamaño total en GB

Dim fso = CreateObject("Scripting.FileSystemObject") 
    Dim profile = fso.GetFolder("folder_path") 
    MsgBox(profile.Size/1073741824) 
Cuestiones relacionadas