2010-07-08 41 views
5

tôi cần phải tính toán kích thước thư mục trong VB NetCách tốt nhất để tính kích thước của một thư mục trong VB .NET là gì?

Tôi biết 2 phương pháp sau đây

Phương pháp 1: từ MSDN http://msdn.microsoft.com/en-us/library/system.io.directory.aspx

'Ví dụ sau sẽ tính toán kích thước của một thư mục ' và các thư mục con của nó, nếu có, và hiển thị tổng kích thước 'tính theo 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 

Cách 2: từ 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() 

Cả hai phương pháp hoạt động tốt. Tuy nhiên, họ mất rất nhiều thời gian để tính toán kích thước thư mục nếu có rất nhiều thư mục con. ví dụ: tôi có một thư mục với 150.000 thư mục con. Các phương pháp trên mất khoảng 1 giờ 30 phút để tính toán kích thước của thư mục. Tuy nhiên, nếu tôi kiểm tra kích thước từ cửa sổ phải mất chưa đầy một phút.

Vui lòng đề xuất các cách tốt hơn và nhanh hơn để tính kích thước của thư mục.

Trả lời

3

Though this answer is talking about Python, khái niệm cũng áp dụng ở đây.

Windows Explorer sử dụng hệ thống API gọi FindFirstFileFindNextFile đệ quy để lấy thông tin tập tin, và sau đó có thể truy cập vào kích thước file rất nhanh chóng thông qua các dữ liệu được truyền qua lại thông qua một struct, WIN32_FIND_DATA: http://msdn.microsoft.com/en-us/library/aa365740(v=VS.85).aspx.

Đề xuất của tôi là triển khai các cuộc gọi API này bằng P/Invoke và tôi tin rằng bạn sẽ đạt được hiệu suất đáng kể.

5

Làm công việc song song sẽ làm cho nó nhanh hơn, ít nhất là trên các máy đa lõi. Hãy thử mã C# này. Bạn sẽ phải dịch cho 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

Đây là đoạn mã ngắn và ngọt sẽ hoàn thành công việc. Bạn chỉ cần thiết lập lại các truy cập trước khi bạn gọi hàm

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, vòng đẹp. Bạn có thể cho tôi biết thủ thuật đặt lại bộ đếm ở đây là gì? Tại sao nó vẫn trả về kích thước thư mục phù hợp với tất cả các thư mục con? Tôi chỉ không nhận được nó ... – LuckyLuke82

0

VB Mã dựa trên câu trả lời của 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

Không biên dịch. 'Đã khóa liên tục' chưa được xác định. – stigzler

+0

@stigzler được định nghĩa trong System.Threading. Kiểm tra câu trả lời được cập nhật. – mathiasfk

0

đây này càng ngắn như tôi có thể nhận được nó.

Nó sẽ hiển thị kích thước của thư được chọn trong hộp thư. Bạn sẽ cần một số FolderBrowserDialog để làm việc này.

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

Hãy thử điều này để có được tổng kích thước trong GB

Dim fso = CreateObject("Scripting.FileSystemObject") 
    Dim profile = fso.GetFolder("folder_path") 
    MsgBox(profile.Size/1073741824) 
Các vấn đề liên quan