2010-07-08 3 views
5

ich brauche die Verzeichnisgröße in VB NETWie berechnet man am besten die Größe eines Verzeichnisses in VB .NET?

Ich weiß, die folgenden 2 Verfahren

Methode 1 zu berechnen: von MSDN http://msdn.microsoft.com/en-us/library/system.io.directory.aspx

‚Das folgende Beispiel berechnet die Größe eines Verzeichnisses ‘ und Unterverzeichnisse, falls vorhanden, und zeigt die Gesamtgröße 'in Bytes an.

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 

Methode 2: von 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() 

Beide Verfahren funktionieren. Sie benötigen jedoch viel Zeit, um die Verzeichnisgröße zu berechnen, wenn viele Unterordner vorhanden sind. Zum Beispiel habe ich ein Verzeichnis mit 150.000 Unterordnern. Die obigen Methoden benötigten ungefähr 1 Stunde 30 Minuten, um die Größe des Verzeichnisses zu berechnen. Wenn ich jedoch die Größe von Fenstern überprüfe, dauert es weniger als eine Minute.

Bitte schlagen Sie bessere und schnellere Möglichkeiten vor, um die Größe des Verzeichnisses zu berechnen.

Antwort

3

Though this answer is talking about Python gilt das Konzept auch hier.

Windows Explorer verwendet System-API-Aufrufe FindFirstFile und FindNextFile rekursiv Datei-Informationen, ziehen und dann die Dateigrößen zugreifen kann sehr schnell durch die Daten, die über eine Rück struct, WIN32_FIND_DATA übergeben wird: http://msdn.microsoft.com/en-us/library/aa365740(v=VS.85).aspx.

Mein Vorschlag wäre, diese API-Aufrufe mit P/Invoke zu implementieren, und ich glaube, dass Sie erhebliche Leistungssteigerungen erleben werden.

5

Die parallele Arbeit sollte es zumindest auf Mehrkern-Rechnern schneller machen. Probieren Sie diesen C# -Code aus. Sie müssen für VB.NET übersetzen.

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

Dies ist ein kurzes und nettes Code-Snippet, das die Arbeit erledigt. Sie müssen nur den Zähler zurücksetzen, bevor Sie die Funktion

rufen
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, schöne Schleife Gesamtgröße zu erhalten. Können Sie mir sagen, was ist der Trick mit Zähler hier zurückzusetzen? Warum gibt es immer noch die richtige Ordnergröße mit allen Unterordnern zurück? Ich bekomme es einfach nicht ... – LuckyLuke82

0

VB-Code basiert auf Jamies Antwort:

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

Kompiliert nicht. 'Interlocked' undefiniert. – stigzler

+0

@stigzler ist es in System.Threading definiert. Überprüfen Sie die aktualisierte Antwort. – mathiasfk

0

Hier ist diese so kurz wie ich es bekommen kann.

Es wird die Größe des ausgewählten in einer Nachricht angezeigt. Sie werden eine FolderBrowserDialog in der Form benötigen, damit dies funktioniert.

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

Versuchen Sie dies in GB

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