а давайте использовать FindFirstFile FindNextFile, перепишем пространство имен System.IO на ассемблере, например! я не говорил что мой код самый быстрый, это один из вариантов реализации поиска файлов, средствами, которые предоставляет студия! а оптимизация его это уже дело рук автора поста
P.S. а кричать на чужой код, что он кривой! свой покажи, а потом и поговорим
а давайте использовать FindFirstFile FindNextFile, перепишем пространство имен System.IO на ассемблере, например! я не говорил что мой код самый быстрый, это один из вариантов реализации поиска файлов, средствами, которые предоставляет студия! а оптимизация его это уже дело рук автора поста
P.S. а кричать на чужой код, что он кривой! свой покажи, а потом и поговорим
один из вариантов реализации поиска файлов, средствами, которые предоставляет студия!
fluke, старик, а ты чего кипишуешь? Студия предоставляет много вариантов, но зачем выбирать самый кривой из них?
A ReDim Preserve делать на каждой итерации цикла, это тоже, по твоему, нормально???? Надеюсь, ты не станешь оспаривать тот факт, что твой код кривой? И не надо так бурно реагировать на здоровую критику, лучше скажи спасибо за то, что уму-разуму научила и исправь свой код!
а оптимизация его это уже дело рук автора поста
хм.. а я всегда считала, что этим занимается тот, кто пишет код...
Слушай тебе уже готовый рабочий пример показали(с одномерным массивом)? а ты все пыль подымаешь?
Что там рабочего?
Кроме того что твой пример можно оптимизировать раз в 20, я про него ничего сказать не могу.
а давайте использовать FindFirstFile FindNextFile, перепишем пространство имен System.IO на ассемблере, например! я не говорил что мой код самый быстрый, это один из вариантов реализации поиска файлов, средствами, которые предоставляет студия!
Использование АПИ не даст ощутимых преимуществ перед встроенными средствами .NET тем более на дисковых операциях.
 im Directories As New Dictionary(Of String, List(Of String))
 im Files As New Dictionary(Of String, List(Of String))
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 im Start = Now
PreLoad()
MessageBox.Show(Now.Subtract(Start).ToString)
End Sub
Sub PreLoad()
For Each Drive In DriveInfo.GetDrives
If Drive.DriveType = DriveType.Fixed Then
LoadDirectory(Drive.RootDirectory.FullName)
End If
Next
End Sub
Sub LoadDirectory(ByVal directory As String)
Try
 im SubDirectories = IO.Directory.GetDirectories(directory)
 im SubFiles = IO.Directory.GetFiles(directory)
 im SubDirectoriesList = New List(Of String)(SubDirectories.Length)
 im SubFilesList = New List(Of String)(SubFiles.Length)
 irectories(directory.ToLower) = SubDirectoriesList
Files(directory.ToLower) = SubFilesList
For Each SubDirectory In SubDirectories
SubDirectoriesList.Add(SubDirectory.ToLower)
LoadDirectory(SubDirectory)
Next
For Each File In SubFiles
SubFilesList.Add(File.ToLower)
Next
Catch ex As System.UnauthorizedAccessException
' все хорошо
Catch ex As Exception
Stop
End Try
End Sub
Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
 im Directory As String = Nothing
If Directories.ContainsKey(TextBox1.Text.ToLower) Then
 irectory = TextBox1.Text.ToLower
ElseIf Directories.ContainsKey(TextBox1.Text.ToLower + "\" Then
 irectory = TextBox1.Text.ToLower + "\"
ElseIf TextBox1.Text.Length > 0 AndAlso Directories.ContainsKey(TextBox1.Text.ToLower.Substring(0, TextBox1.Text.Length - 1)) Then
 irectory = TextBox1.Text.ToLower.Substring(0, TextBox1.Text.Length - 1)
End If
If Directory IsNot Nothing Then
 im ChildFiles As New List(Of String)
FilesCount.Text = GetContent(Directory, ChildFiles).ToString
 irectoryFiles.DataSource = ChildFiles
Else
FilesCount.Text = ""
 irectoryFiles.DataSource = Nothing
End If
End Sub
Function GetContent(ByVal directory As String, ByRef childFiles As List(Of String)) As Integer
 im Count = 0
If Files.ContainsKey(directory) Then
 im F = Files(directory)
Count = F.Count
If childFiles.Count < 1000 Then
childFiles.AddRange(F)
End If
End If
If Directories.ContainsKey(directory) Then
For Each SubDirectory In Directories(directory)
Count += GetContent(SubDirectory, childFiles)
Next
End If
Return Count
End Function
End Class
Вобщем код выполняет следующее.
При запуске программы загружает структуру файловой системы в память.
При вводе в поле названия папки показывает сколько файлов в папке и под папках плюс выводит список первых 1000 файлов (если показывать больше, то листбокс просто тормозит).
Предварительная загрузка занимает около 10 секунд, дальнейшая работа полностью интерактивна, т.е. кванты времени не фиксируемые на глаз (если замерять программно - около 0.05 секунд)
Работает на ассоциативных списках, есть куда увеличивать скорость (самое банальное - предрассчитывать кол-во файлов в подпапках).
Можешь написать такое же но на обычном массиве так чтоб это работало быстрее?
Я например реально могу.
PS Код Form1.designer.vb:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.Label1 = New System.Windows.Forms.Label
Me.FilesCount = New System.Windows.Forms.Label
Me.DirectoryFiles = New System.Windows.Forms.ListBox
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.TextBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append
Me.TextBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.FileSystemDirectories
Me.TextBox1.Location = New System.Drawing.Point(12, 25)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(434, 20)
Me.TextBox1.TabIndex = 0
'
'Label1
'
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(9, 9)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(110, 13)
Me.Label1.TabIndex = 1
Me.Label1.Text = "Количество файлов:"
'
'FilesCount
'
Me.FilesCount.AutoSize = True
Me.FilesCount.Location = New System.Drawing.Point(125, 9)
Me.FilesCount.Name = "FilesCount"
Me.FilesCount.Size = New System.Drawing.Size(13, 13)
Me.FilesCount.TabIndex = 2
Me.FilesCount.Text = "0"
'
'DirectoryFiles
'
Me.DirectoryFiles.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.DirectoryFiles.FormattingEnabled = True
Me.DirectoryFiles.IntegralHeight = False
Me.DirectoryFiles.Location = New System.Drawing.Point(12, 51)
Me.DirectoryFiles.Name = "irectoryFiles"
Me.DirectoryFiles.Size = New System.Drawing.Size(434, 453)
Me.DirectoryFiles.TabIndex = 3
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(458, 516)
Me.Controls.Add(Me.DirectoryFiles)
Me.Controls.Add(Me.FilesCount)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents FilesCount As System.Windows.Forms.Label
Friend WithEvents DirectoryFiles As System.Windows.Forms.ListBox
Dim Directories As New Dictionary(Of String, List(Of String))
Dim Files As New Dictionary(Of String, List(Of String))
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Start = Now
PreLoad()
MessageBox.Show(Now.Subtract(Start).ToString)
End Sub
Sub PreLoad()
For Each Drive In DriveInfo.GetDrives
If Drive.DriveType = DriveType.Fixed Then
LoadDirectory(Drive.RootDirectory.FullName)
End If
Next
End Sub
Sub LoadDirectory(ByVal directory As String)
Try
Dim SubDirectories = IO.Directory.GetDirectories(directory)
Dim SubFiles = IO.Directory.GetFiles(directory)
Dim SubDirectoriesList = New List(Of String)(SubDirectories.Length)
Dim SubFilesList = New List(Of String)(SubFiles.Length)
 irectories(directory.ToLower) = SubDirectoriesList
Files(directory.ToLower) = SubFilesList
For Each SubDirectory In SubDirectories
SubDirectoriesList.Add(SubDirectory.ToLower)
LoadDirectory(SubDirectory)
Next
For Each File In SubFiles
SubFilesList.Add(File.ToLower)
Next
Catch ex As System.UnauthorizedAccessException
' все хорошо
Catch ex As Exception
Stop
End Try
End Sub
Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Dim Directory As String = Nothing
If Directories.ContainsKey(TextBox1.Text.ToLower) Then
 irectory = TextBox1.Text.ToLower
ElseIf Directories.ContainsKey(TextBox1.Text.ToLower + "\" Then
 irectory = TextBox1.Text.ToLower + "\"
ElseIf TextBox1.Text.Length > 0 AndAlso Directories.ContainsKey(TextBox1.Text.ToLower.Substring(0, TextBox1.Text.Length - 1)) Then
 irectory = TextBox1.Text.ToLower.Substring(0, TextBox1.Text.Length - 1)
End If
If Directory IsNot Nothing Then
Dim ChildFiles As New List(Of String)
FilesCount.Text = GetContent(Directory, ChildFiles).ToString
 irectoryFiles.DataSource = ChildFiles
Else
FilesCount.Text = ""
 irectoryFiles.DataSource = Nothing
End If
End Sub
Function GetContent(ByVal directory As String, ByRef childFiles As List(Of String)) As Integer
Dim Count = 0
If Files.ContainsKey(directory) Then
Dim F = Files(directory)
Count = F.Count
If childFiles.Count < 1000 Then
childFiles.AddRange(F)
End If
End If
If Directories.ContainsKey(directory) Then
For Each SubDirectory In Directories(directory)
Count += GetContent(SubDirectory, childFiles)
Next
End If
Return Count
End Function
End Class
Вобщем код выполняет следующее.
При запуске программы загружает структуру файловой системы в память.
При вводе в поле названия папки показывает сколько файлов в папке и под папках плюс выводит список первых 1000 файлов (если показывать больше, то листбокс просто тормозит).
Предварительная загрузка занимает около 10 секунд, дальнейшая работа полностью интерактивна, т.е. кванты времени не фиксируемые на глаз (если замерять программно - около 0.05 секунд)
Работает на ассоциативных списках, есть куда увеличивать скорость (самое банальное - предрассчитывать кол-во файлов в подпапках).
Можешь написать такое же но на обычном массиве так чтоб это работало быстрее?
Я например реально могу.
PS Код Form1.designer.vb:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.Label1 = New System.Windows.Forms.Label
Me.FilesCount = New System.Windows.Forms.Label
Me.DirectoryFiles = New System.Windows.Forms.ListBox
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.TextBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append
Me.TextBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.FileSystemDirectories
Me.TextBox1.Location = New System.Drawing.Point(12, 25)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(434, 20)
Me.TextBox1.TabIndex = 0
'
'Label1
'
Me.Label1.AutoSize = True
Me.Label1.Location = New System.Drawing.Point(9, 9)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(110, 13)
Me.Label1.TabIndex = 1
Me.Label1.Text = "Количество файлов:"
'
'FilesCount
'
Me.FilesCount.AutoSize = True
Me.FilesCount.Location = New System.Drawing.Point(125, 9)
Me.FilesCount.Name = "FilesCount"
Me.FilesCount.Size = New System.Drawing.Size(13, 13)
Me.FilesCount.TabIndex = 2
Me.FilesCount.Text = "0"
'
'DirectoryFiles
'
Me.DirectoryFiles.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.DirectoryFiles.FormattingEnabled = True
Me.DirectoryFiles.IntegralHeight = False
Me.DirectoryFiles.Location = New System.Drawing.Point(12, 51)
Me.DirectoryFiles.Name = "irectoryFiles"
Me.DirectoryFiles.Size = New System.Drawing.Size(434, 453)
Me.DirectoryFiles.TabIndex = 3
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(458, 516)
Me.Controls.Add(Me.DirectoryFiles)
Me.Controls.Add(Me.FilesCount)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents FilesCount As System.Windows.Forms.Label
Friend WithEvents DirectoryFiles As System.Windows.Forms.ListBox
насчет скорости АПИ по сравнению со встроенными классами, я готов спорить и практика показывает 2-3 кратный прирост скорости! люди вернитесь к названию поста! человеку может, нужен просто список файлов! и быстродействие для него не критично! а вы уже предлагаете ему программную "кофеварку"
ReDim Preserve, если тут, собрались такие знатоки коллекций, то может Ника, мне расскажет как в коллекции при вызове метода Add(item) изменяется ее размерность? просто Redim, базару нет, медленно, так как приходиться переопределять весь массив! а Redim Preserve изменяет только его верхнюю границу! и время потраченное, по сравнению с дисковой операциями можно не считывать!
насчет скорости АПИ по сравнению со встроенными классами, я готов спорить и практика показывает 2-3 кратный прирост скорости!
Практику сравнения ассоциативных списков и одномерных массивов мы уже прошли значит.
Хорошо, что ты предлагаешь в плане АПИ сравнивать?
Давай тот же FindFirstFile/FindNextFile - ты делаешь это на АПИ, я делаю встроенным классом, годится?
Function LoadAllFiles() As List(Of String)
Dim result As New List(Of String)
For Each Drive In DriveInfo.GetDrives
If Drive.DriveType = DriveType.Fixed Then
LoadFiles(Drive.RootDirectory.FullName, result)
End If
Next
Return result
End Function
Sub LoadFiles(ByVal path As String, ByVal files As List(Of String))
Try
files.AddRange(IO.Directory.GetFiles(path))
For Each SubDirectory In IO.Directory.GetDirectories(path)
LoadFiles(SubDirectory, files)
Next
Catch ex As UnauthorizedAccessException
' все хорошо
End Try
End Sub
Sub Main()
Dim start = Now
Dim Files = LoadAllFiles()
Console.WriteLine(Now.Subtract(start))
End Sub
Винт 400 ГБ, 3 раздела, занято 300+ ГБ, всего 321 056 файлов, время работы 9 секунд с лишним.
Предлагай свой вариант - поспорим, оценим.
вернитесь к названию поста! человеку может, нужен просто список файлов!
Человек сам четко не указал что именно ему нужно, но исходя из того что он написал, мое предложение весьма разумно.
у меня вопрос к Нике, как по ее мнению происходит добавления элемента в коллекцию? иметься ввиду не оберточный метод Add, а то, как сам метод это делает! ведь любой элемент коллекции это элемент массива, только на более низком уровне! жду ответа))
ReDim Preserve, если тут, собрались такие знатоки коллекций, то может Ника, мне расскажет как в коллекции при вызове метода Add(item) изменяется ее размерность? просто Redim, базару нет, медленно, так как приходиться переопределять весь массив! а Redim Preserve изменяет только его верхнюю границу!
Ты не прав.
В .NET нет возможности изменить верхнюю размерность массива (если откроешь MSDN то увидишь что подобного метода нет).
Единственное что можно сделать - создать новый массив бОльшего размера и в него скопировать.
Redim Preserve - это всего лишь синтаксический сахар, и при компиляции это первращается в вызов Utils.CopyArray
Физически - выделяется новый блок памяти, в него копируются данные, старый блок освобождается (когда - неизвестно, когда запустится сборщик мусора, но точно не моментально)
Нужно говорить о том что постоянное дергание памяти туда-сюда займет очень много времени?
Причем чем больше массив, тем больше времени это будет занимать, а в определенный момент скорость вообще упадет до нуля - когда кончитс ОЗУ и пойдет своппинг.
и время потраченное, по сравнению с дисковой операциями можно не считывать!
Еще один бенчмарк?
Пожалуйста.
Аналог моего предыдцщего кода
Function LoadAllFiles() As String()
Dim result = New String(0) {}
For Each Drive In DriveInfo.GetDrives
If Drive.DriveType = DriveType.Fixed Then
LoadFiles(Drive.RootDirectory.FullName, result)
End If
Next
Return result
End Function
Sub LoadFiles(ByVal path As String, ByRef files As String())
Try
Dim CurrentFiles = IO.Directory.GetFiles(path)
Dim WasFiles = files.Length
ReDim Preserve files(WasFiles + CurrentFiles.Length - 1)
For i = 0 To CurrentFiles.Length - 1
files(i + WasFiles) = CurrentFiles(i)
Next
For Each SubDirectory In IO.Directory.GetDirectories(path)
LoadFiles(SubDirectory, files)
Next
Catch ex As UnauthorizedAccessException
' все хорошо
End Try
End Sub
Скорость работы просто катастрофическая - 3 минуты с Redim Preserve против 9 секунд с List.Add