I think that you're friggin whacked kid.
Erm, that's not exactly the kind of useful response I was hoping for.
But let's roll with it, while I wait for anyone else to answer my
question.
maybe you're trying to store 88,000 items in an array?
Erm, no. That's rather silly.
give us more information; i have a similar project that gave the exact
opposite results... .NET enumerating of folders / files was quite a
bit faster than anything i could do in vb6
VB6 wasn't so great in this department either. That's why I learned to
use the API in the first place.
As currently configured, the test program recursively scans the entire
C: drive, counting files and dirs. It also grabs the size, attribs,
and all three timestamps of each file/dir it encounters and stores them
in a structure which could be used for something productive, but in
this case is promptly discarded. I do it only to make sure the
information is actually read. Two methods are used, the
System.IO.DirectoryInfo, and API calls. I made sure as much as
possible is similar in the two versions, so that the only substantial
time difference is in the .NET/API call.
I also *disregard* the first run, as it suffers a penalty - the
directory info is actually being read from the disk. After that, it's
cached; assuming your memory is big enough and your drive small enough.
By the way, my C: drive has 240,295 files in 16,784 folders. I ran the
test both from the .NET 2.0 IDE and from the Release .exe, and here are
the results:
System.IO.DirectoryInfo, run from IDE: 80,734 ms (milliseconds)
System.IO.DirectoryInfo, Release .exe: 43,671 ms
Windows API, run from IDE: 5,812 ms
Windows API, Release .exe: 4,047 ms
These results are even worse than my initial ones. But at this point,
it doesn't really matter to me *how* ridiculously slow it is - it's
still ridiculously slow. Way more overhead than expected for using the
..NET method (which just calls the API anyway), and unacceptable for a
number of uses I have planned.
I invite you to try this yourself, get your own results, and draw your
own conclusions. And let me know what they are.
Create a new project, add two buttons to a form, delete existing code,
and paste this in (watch out for wordwrap):
-----
Imports System.Runtime.InteropServices
Public Class Form1
Private Const INVALID_HANDLE_VALUE As Integer = -1
Private Const MAX_PATH As Integer = 260
Structure tFILETIME
Dim dwLowDateTime As Int32
Dim dwHighDateTime As Int32
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Private Structure WIN32_FIND_DATA
Public dwFileAttributes As Integer
Public ftCreationTime As tFILETIME
Public ftLastAccessTime As tFILETIME
Public ftLastWriteTime As tFILETIME
Public nFileSizeHigh As UInt32
Public nFileSizeLow As UInt32
Public dwReserved0 As Int32
Public dwReserved1 As Int32
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _
Public cFileName As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> _
Public cAlternateFileName As String
End Structure
Private Declare Function FindFirstFile Lib "kernel32" Alias
"FindFirstFileA" (ByVal lpFileName As String, ByRef lpFindFileData As
WIN32_FIND_DATA) As Int32
Private Declare Function FindNextFile Lib "kernel32" Alias
"FindNextFileA" (ByVal hFindFile As Int32, ByRef lpFindFileData As
WIN32_FIND_DATA) As Int32
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As
Int32) As Int32
Public Structure DirItem
Dim Name As String
Dim Size As Long
Dim Attribs As System.IO.FileAttributes
Dim DateAccessed As Date
Dim DateCreated As Date
Dim DateModified As Date
End Structure
Dim Files, Dirs As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Test(1)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Test(2)
End Sub
Sub Test(ByVal Method As Integer)
Dim StartTick As Integer = My.Computer.Clock.TickCount
Files = 0
Dirs = 0
Select Case Method
Case 1 : RecurseDirsNet("c:")
Case 2 : RecurseDirsAPI("c:")
End Select
MsgBox("Files = " & Files & vbCrLf & "Dirs = " & Dirs & vbCrLf &
"Time (ms)= " & (My.Computer.Clock.TickCount - StartTick))
End Sub
Public Sub RecurseDirsAPI(ByVal Path As String)
Dim s1 As String
Dim WFD As New WIN32_FIND_DATA
Dim x As DirItem
Dim hDir As Integer = FindFirstFile(Path & "\*.*", WFD)
If hDir = INVALID_HANDLE_VALUE Then Stop
Do
x = New DirItem
s1 = StripNull(WFD.cFileName)
If s1 <> "." And s1 <> ".." Then
With x
.Name = s1
.Size = WFD.nFileSizeLow + WFD.nFileSizeHigh * 4294967296
.Attribs = WFD.dwFileAttributes
.DateAccessed = FileTimeConvert(WFD.ftLastAccessTime)
.DateCreated = FileTimeConvert(WFD.ftCreationTime)
.DateModified = FileTimeConvert(WFD.ftLastWriteTime)
If .Attribs And IO.FileAttributes.Directory Then
Dirs += 1
RecurseDirsAPI(Path & "\" & .Name)
Else
Files += 1
End If
End With
End If
If FindNextFile(hDir, WFD) = 0 Then Exit Do
Loop
FindClose(hDir)
End Sub
Public Sub RecurseDirsNet(ByVal Path As String)
Dim x As DirItem
Dim DI As New System.IO.DirectoryInfo(Path & "\")
For Each File As System.IO.FileInfo In DI.GetFiles
x = New DirItem
With x
.Name = File.Name
.Attribs = File.Attributes
.DateAccessed = File.LastAccessTime
.DateCreated = File.CreationTime
.DateModified = File.LastWriteTime
End With
Files += 1
Next
For Each Dir As System.IO.DirectoryInfo In DI.GetDirectories
x = New DirItem
With x
.Name = Dir.Name
.Attribs = Dir.Attributes
.DateAccessed = Dir.LastAccessTime
.DateCreated = Dir.CreationTime
.DateModified = Dir.LastWriteTime
Dirs += 1
RecurseDirsNet(Path & "\" & .Name)
End With
Next
End Sub
Function StripNull(ByVal X As String) As String
Dim l1 As Long : l1 = InStr(1, X, Chr(0), vbBinaryCompare)
If l1 = 0 Then
StripNull = X
Else
StripNull = Strings.Left(X, l1 - 1)
End If
End Function
Private Function FileTimeConvert(ByVal udtFileTime As tFILETIME) As
Date
FileTimeConvert =
System.DateTime.FromFileTime(udtFileTime.dwLowDateTime +
udtFileTime.dwHighDateTime * 4294967296)
End Function
End Class