Listing a Directory
Version 0.5.1 Needed: This tutorial needs VBCorLib v0.5.1 or it will produce
an incorrectly formatted output.
In this tutorial the DirectoryInfo class will be used to retrieve all of the
files and directories contained within a specified directory and lists them. This provides a handy way to list files and
directories to users. Along with the DirectoryInfo class, the FileInfo
class and FileSystemInfo interface will be introduced.
Many common tasks involve some kind of directory listing. Anything from a list of names or
subdirectoris to the size of each file may be required. Using DirectoryInfo a list of all the
entries can be retrieved for further processing.
We start off by creating a new DirectoryInfo object with the directory we
want to list.
' create a DirectoryInfo for the current directory
Dim Dir As DirectoryInfo
Set Dir = NewDirectoryInfo(".")
This will create a new DirectoryInfo object that is initialized to the specified
directory. The directory will not be validated at this point, so any path that is
specified is considered valid.
For our listing, we want to show the actual directory that is going to be listed.
This is accomplished by requesting the full path of the directory specified.
' output the directory we are going to list
Debug.Print "Directory to list: " & Path.GetFullPath(Dir.ToString)
By using Path.GetFullPath the entire directory tree is created up to the
original directory specified, which was the current directory. The directory is still
not validated at this point. These are formatting functions that build a correctly
formatted directory path.
For the listing we would like to also display some column headers to help identify
the information being displayed. We will display 4 pieces of information from each
directory entry: Name, Size, Type, Creation Time. Lets also define a maximum length
for the entry names. This will be used in formatting the outputs.
' a name can be a maximum of 25 characters
Const MaxNameLength As Long = 25
' output header information
Debug.Print cString.Format("{0,-" & MaxNameLength & "} {1,12} {2,-12} {3,-20:g}", _
"Name", "Size", "Type", "Creation Time")
Debug.Print "------------------------------------------------------------------"
This will create a formatted header with column widths defined. Negative values are used
for the column width so the value to be placed will be left-aligned within the column.
'Size' will be right-aligned since it has a positive width.
Now that we have some headers displayed, the directory entries can be retrieved.
' this will return atleast a zero-length array.
Dim fsi() As FileSystemInfo
fsi = Dir.GetFileSystemInfos
As you can see, retrieving all of the entries within the specified directory is trivial.
This will return an array of FileSystemInfo objects, each representing a file
or subdirectory in the specified DirectoryInfo path. If there are no files
or subdirectories, then an empty array is returned. The array is not uninitialized,
but will have a length of 0.
Now that we have a list of entries, all that is needed to be done is iterate through
the array and display the appropriate information for each entry.
' declarations used within the loop
Dim i As Long
Dim fsiType As String
Dim fsiName As String
Dim size As Long
Dim f As FileInfo
' if there are 0 elements in the array, then UBound will return -1.
For i = 0 To UBound(fsi)
' only files have a length
If TypeOf fsi(i) Is FileInfo Then
' and we must cast in order to get the length.
Set f = fsi(i)
size = f.Length
fsiType = "File"
Else
' set the size and entry type for a directory
size = 0
fsiType = "Directory"
End If
' ... output formatted information; shown below
Next
Since both files and directories are valid FileSystemInfo objects, we must
determine which type is being processed as we iterate through the loop. To achieve
this the current FileSystemInfo object is tested to see if it is also a
FileInfo object. We need to retrieve the length of files only, so a FileInfo
object is required.
As each entry is processed, it is printed out in a readable format matching
the column headers displayed earlier. The name of each entry is tested against
the maximum name length defined and truncates as necessary. Once all information
has been collected, it can be displayed in the same manner as used to format
the column headers.
' make the name fit in the column.
fsiName = fsi(i).name
If Len(fsiName) > MaxNameLength Then fsiName = Left$(fsiName, MaxNameLength)
' output formatted summary f the entry.
Debug.Print cString.Format("{0, -" & MaxNameLength & "} {1,10:N0}KB {2, -12} {3,-20:g}", _
fsiName, size / 1000, fsiType, fsi(i).creationTime)
There are a couple differences in the formatting. Primarily because now numbers are
being displayed. We want to show the length of a file in kilobytes, not total bytes,
so the (N)umber format with (0) decimal digits formatting is specified for the length
that is (size / 1000). (g)eneral is specified for the creation time. This will vary
depending on regional settings, but should display a date and time.
Running this example will produce an output similar to the following:
Directory to list: C:\Program Files\Microsoft Visual Studio\VB98
Name Size Type Creation Time
------------------------------------------------------------------
ADDSCCUS.DLL 77KB File 5/22/1998 12:00 AM
BIBLIO.MDB 3,611KB File 4/24/1998 12:00 AM
Binary.bin 0KB File 9/23/2004 11:31 AM
C2.EXE 692KB File 7/15/2000 12:00 AM
CoTaskMemLeak.exe 20KB File 10/2/2004 10:32 AM
CVPACK.EXE 82KB File 6/17/1998 12:00 AM
Below is the full listing of the example for easier copying and pasting.
Private Sub ListDirectory()
' get the current directory.
Dim Dir As DirectoryInfo
Set Dir = NewDirectoryInfo(".")
' output the directory we are getting the entries from.
Debug.Print "Directory to list: " & Path.GetFullPath(Dir.ToString)
'Dim MaxNameLength As Long
Const MaxNameLength As Long = 25
' output header information
Debug.Print cString.Format("{0,-" & MaxNameLength & "} {1,12} {2,-12} {3,-20:g}", _
"Name", "Size", "Type", "Creation Time")
Debug.Print "------------------------------------------------------------------"
' will return atleast a zero-length array.
Dim fsi() As FileSystemInfo
fsi = Dir.GetFileSystemInfos
Dim i As Long
Dim fsiType As String
Dim fsiName As String
Dim size As Long
Dim f As FileInfo
For i = 0 To UBound(fsi)
' only files have a length
If TypeOf fsi(i) Is FileInfo Then
' and we must cast in order to get the length.
Set f = fsi(i)
size = f.Length
fsiType = "File"
Else
size = 0
fsiType = "Directory"
End If
' make the name fit in the column.
fsiName = fsi(i).name
If Len(fsiName) > MaxNameLength Then fsiName = Left$(fsiName, MaxNameLength)
' output formatted entry.
Debug.Print cString.Format("{0, -" & MaxNameLength & "} {1,10:N0}KB {2, -12} {3,-20:g}", _
fsiName, size / 1000, fsiType, fsi(i).creationTime)
Next
End Sub
As you can see, getting a list of entries is a simple task and only needs
minimal processing to extract additional information. This removes many of the
burdens that can be encountered which may originally needed to be written
from scratch.
Many concepts were covered in this relatively short example. Things from retrieving
lists from directories to formatting outputs were touched upon. Hopefully some of these
concepts will help produce better, more robust code in the future.
|