2010-07-08 8 views
5

Ho bisogno per calcolare la dimensione di directory in VB .NetQual è il modo migliore per calcolare la dimensione di una directory in VB .NET?

so i seguenti 2 metodi

Metodo 1: da MSDN http://msdn.microsoft.com/en-us/library/system.io.directory.aspx

'L'esempio seguente calcola la dimensione di una directory ' e le sue sottodirectory, se presenti, e visualizza la dimensione totale 'in byte.

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 

Metodo 2: da 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() 

Entrambi questi metodi funzionano bene. Tuttavia richiedono molto tempo per calcolare la dimensione della directory se ci sono molte sottocartelle. Ad esempio, ho una directory con 150.000 sottocartelle. I metodi di cui sopra hanno impiegato circa 1 ora e 30 minuti per calcolare la dimensione della directory. Tuttavia, se controllo la dimensione da windows ci vuole meno di un minuto.

Si prega di suggerire modi migliori e più veloci per calcolare la dimensione della directory.

risposta

3

Though this answer is talking about Python, il concetto si applica anche qui.

di Windows Explorer utilizza sistema di chiamate API FindFirstFile e FindNextFile ricorsivamente per tirare le informazioni sul file, e quindi in grado di accedere ai file di dimensioni molto rapidamente attraverso i dati che è passato di nuovo attraverso un struct, WIN32_FIND_DATA: http://msdn.microsoft.com/en-us/library/aa365740(v=VS.85).aspx.

Il mio suggerimento sarebbe quello di implementare queste chiamate API utilizzando P/Invoke, e credo che si verificheranno miglioramenti significativi delle prestazioni.

5

Fare il lavoro in parallelo dovrebbe renderlo più veloce, almeno su macchine multi-core. Prova questo codice C#. Dovrai tradurre per 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

Questo è uno snippet di codice breve e dolce che porterà a termine il lavoro. Hai solo bisogno di azzerare il contatore prima di chiamare la funzione

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, bel ciclo. Puoi dirmi qual è il trucco con il contatore di reset qui? Perché restituisce comunque la giusta dimensione della cartella con tutte le sottocartelle? Io proprio non capisco ... – LuckyLuke82

0

codice VB in base alla risposta di 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

Non si compila. 'Interbloccato' indefinito. – stigzler

+0

@stigzler è definito in System.Threading. Controlla la risposta aggiornata. – mathiasfk

0

qui più breve posso farlo.

Verrà visualizzata la dimensione del selezionato in una finestra di messaggio. Avrai bisogno di un FolderBrowserDialog nel modulo affinché funzioni.

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

Prova questo per ottenere dimensione totale in GB

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