2010-07-08 5 views
5

J'ai besoin de calculer la taille de répertoire en VB .NetQuelle est la meilleure façon de calculer la taille d'un répertoire dans VB .NET?

Je sais que les 2 méthodes suivantes

Méthode 1: à partir de MSDN http://msdn.microsoft.com/en-us/library/system.io.directory.aspx

« L'exemple suivant calcule la taille d'un répertoire » et ses sous-répertoires, le cas échéant, et affiche la taille totale 'en octets.

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éthode 2: à partir 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() 

Ces deux méthodes fonctionnent très bien. Cependant, ils prennent beaucoup de temps pour calculer la taille du répertoire s'il y a beaucoup de sous-dossiers. Par exemple, j'ai un répertoire avec 150 000 sous-dossiers. Les méthodes ci-dessus ont pris environ 1 heure 30 minutes pour calculer la taille du répertoire. Cependant, si je vérifie la taille des fenêtres cela prend moins d'une minute.

S'il vous plaît suggérer des moyens meilleurs et plus rapides pour calculer la taille du répertoire.

Répondre

3

Though this answer is talking about Python, le concept s'applique également ici.

Explorateur Windows utilise l'API des appels système FindFirstFile et FindNextFile récursive pour extraire des informations de fichiers et peut alors accéder à la taille des fichiers très rapidement les données qui passe par un retour struct, WIN32_FIND_DATA: http://msdn.microsoft.com/en-us/library/aa365740(v=VS.85).aspx. Ma suggestion serait de mettre en œuvre ces appels d'API en utilisant P/Invoke, et je crois que vous constaterez des gains de performance significatifs.

5

Faire le travail en parallèle devrait le rendre plus rapide, au moins sur les machines multi-cœurs. Essayez ce code C#. Vous devrez traduire pour 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

Ceci est un extrait de code court et doux qui fera le travail. Vous avez juste besoin de réinitialiser le compteur avant d'appeler la fonction

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, belle boucle. Pouvez-vous me dire quel est le truc avec le compteur de réinitialisation ici? Pourquoi retourne-t-il toujours la bonne taille de dossier avec tous les sous-dossiers? Je ne comprends pas ... – LuckyLuke82

0

code VB basé sur la réponse 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

Ne compile pas. 'Interlocked' indéfini. – stigzler

+0

@stigzler est défini dans System.Threading. Vérifiez la réponse mise à jour. – mathiasfk

0

Voici ce aussi court que je peux l'obtenir.

Il affichera la taille de la sélectionnée dans une boîte de message. Vous aurez besoin d'un FolderBrowserDialog dans le formulaire pour que cela fonctionne.

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

Essayez ceci pour obtenir la taille totale GB

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