VB6's File System Objects
by Peter G. Aitken
File System Objects (FSO) completely
recast Visual Basics fundamental powers over disk storage
in an object-oriented mold. It makes file access and management
considerably easier, even though it isnt quite complete.
Ill take an in-depth look at one of the new toys
that the Redmondians have provided in VB6: the object-oriented file
access and management system, called File System Objects (FSO).
This isnt one of the flashier additions to the new version
of Visual Basic, and it certainly has not gotten the same
attention as, say, ActiveX Data Objects or Dynamic HTML. Even so,
its an important improvement to the language, one that you
should begin using in your own programs as soon as possible. FSO
really doesnt let you do anything that cannot be done with
the old file-oriented commands, but it makes many tasks much
easier. Perhaps most important is that FSO moves file access and
manipulation from the realm of procedural programming to the
modern realm of object-oriented programming, with all the
advantages that entails.
There is, however, one fly in the ointment.
While the FSO framework for file management (creating folders,
moving and deleting files, and so on) seems to be complete, the
file access part of FSO (writing data to and reading data from
files) is only partially complete. To be precise, you can read
and write only sequential text filesfor random access and
binary files, you are still limited to the traditional Basic
statements. I am sure this limitation will be corrected soon, but
for now youll just have to live with it.
Some of the material in this column is adapted
from my newest Coriolis Group book, Visual Basic 6
Programming Blue Book.
Text File Access with FSO
The top dog in the FSO hierarchy is the FileSystemObject
class. To read or write a text file, you must first create an
instance of this class:
Dim myFSO
Set myFSO = _
CreateObject("Scripting.FileSystemObject")
The following alternate syntax accomplishes the
same thing:
Dim myFSO As New
Scripting.FileSystemObject
The Scripting qualifier
identifies the library in which the FileSystemObject
class is defined. To use the class, you do not need to select the
Microsoft Scripting Runtime library in the Visual Basic
References dialog box, but doing so will give you access to the
classes, methods, and properties in the Object Browser. (If you
are not familiar with the Object Browser, you owe it to yourself
to find out; it is a great source of information about classes.)
After creating an instance of the FileSystemObject
class, the next step is to create a TextStream
object. A TextStream object is nothing more than
a regular text file enclosed in an FSO wrapper. The FileSystemObject
has two methods for creating TextStream objects:
- CreateTextFile creates a
new text file. If a file of the same name already exists,
it is overwritten.
- OpenTextFile opens a text
file for reading and/or writing. If the file already
exists, new data is appended to existing data.
The syntax for these methods is similar. In
these examples, assume that myFSO is a FileSystemObject
and that it has been declared as a type Variant
or Object. The first line of code creates a new
file, and the second line opens an existing file:
Set ts =
myFSO.CreateTextFile(filename[, overwrite[, unicode]])
Set ts = myFSO.OpenTextFile(filename[, iomode[, create[,_
format]]])
Filename is a string
expression specifying the name (including path information) of
the file. The overwrite argument is either True
or False, indicating whether an existing file
will be overwritten. If this argument is omitted, the default is False.
If overwrite is False and filename
already exists, an error occurs. You can trap this error to
permit the user to verify file overwrites. Set unicode
to True to create a Unicode file, or False
(the default) for an ASCII file. Set iomode to
the constants ForReading or ForAppending
to read the file or write data to the end of the file,
respectively. A file opened using ForReading
cannot be written to. Set create to True
or False to specify whether a new file will be
created if the file named in the filename
argument does not exist. The default is False.
The format argument is a tristate argument (that
is, one that can take on one of three possible values) that
determines the format of the file:
- TriStateTrue opens the
file as Unicode.
- TriStateFalse (the
default) opens the file as ASCII.
- TristateUseDefault uses
the system default format setting.
What Is Unicode?
When
dealing with text, computers use numbers to represent
characters, punctuation marks, and so on. The two most
commonly used systems for this are ASCII (or ANSI) and
Unicode. ASCII uses one byte per character, permitting
only 256 different symbols to be represented. This is
adequate for English but cannot support many other
languages. Unicode uses 2 bytes per character, permitting
over 65,000 different symbols. Which format you use
depends on the specific requirements of your project.
|
Another way to obtain a TextStream
object is to create a File object and then use
its OpenAsTextStream method. This method works
with existing files only. Creating a File object
is done like this, assuming that myFSO is a FileSystemObject:
Dim f
Set f = myFSO.GetFile(filename)
If the file does not already exist, you can
take the following approach, using CreateTextFile
to create the file before creating the File
object:
myFSO.CreateTextFile filename
Set f = myFSO.GetFile(filename)
After creating the File
object, you can invoke the Open-AsTextStream
method. The syntax is:
f.OpenAsTextStream([iomode,
[format]])
The iomode and format
arguments are the same as described above for the CreateTextFile
and OpenTextFile methods. Heres the code
necessary to create a TextStream object
associated with an existing file DEMO.TXT for reading, using the OpenAsTextStream
method:
Dim myFSO, f, ts
Set myFSO = CreateObject("Scripting.FileSystemObject")
Set f = myFSO.GetFile("demo.txt")
Set ts = f.OpenAsTextStream(ForWriting, _
TristateUseDefault)
Once you have created a TextStream
object, you use its properties and methods to write and read
text. The objects properties are listed in Table 1. In
reading this table, be aware that the TextStream
object always has a current character position, also called the
file pointer, that indicates where the next read or write
operation will take place. All of these properties are read-only.
Table 1. Properties of the TextStream
object.
| Property |
Description |
| AtEndOfLine |
True if the file pointer is at the
end of a line; False otherwise. This
property applies only to TextStream
files that are open for reading; otherwise, an error
occurs. |
| AtEndOfStream |
True if the file pointer is at the
end of the file; False otherwise. This
property applies only to TextStream
files that are open for reading; otherwise, an error
occurs. |
| Column |
Returns the column number of the file pointer. The
first character on a line is at column 1. |
| Line |
Returns the current line number. |
|
The TextStream object has a
number of methods to read and write data. These methods are
described in Table 2.
Table 2. Methods of the TextStream
object.
| Property |
Description |
| Close |
Closes the file associated with the TextStream
object. Always execute the Close method
when you are done reading/writing the file. |
| Read(n) |
Reads the next n characters from the file and returns
the resulting string. |
| ReadAll |
Reads the entire file and returns the resulting
string. |
| ReadLine |
Reads an entire line (up to, but not including, the
newline character) from a TextStream
file and returns the resulting string. |
| Skip(n) |
Skips ahead (moves the file pointer) by n characters. |
| SkipLine |
Skips to the beginning of the next line. |
| Write(s) |
Writes the string s to the file. No extra or newline
characters are added. |
| WriteBlankLines(n) |
Writes n blank lines to the file. |
| WriteLine(s) |
Writes the string s to the file followed by a newline
character. |
|
Be aware that certain of these methods are
applicable only when the file has been opened for reading or
writing. If you try to use a method that is inappropriate for the
files mode, an error will occur.
File Management with FSO
As with file access, file management with FSO
is based upon the FileSystemObject class. Ive
already shown you how to create an instance of this class. Once
you have done this, you can use its properties and methods to
perform the file manipulation tasks required by your program.
As mentioned earlier, the FileSystemObject
is the top object in the FSO hierarchy. As such, it
provides access to all of the systems drives (both local
and network), folders, and files. There are several other objects
in the hierarchy, and you can see that they correspond to the way
in which disk drives are organized:
- Drive object, which
corresponds to a single disk drive on the system.
- Folder object, which
corresponds to a single folder on a drive.
- File object, which
corresponds to a single file in a folder.
The following is a brief overview of how the
FSO system works. The FileSystemObject has a Drives
collection that contains one Drive object for
each local and network drive. You can query a Drive
objects properties to obtain information about the drive,
such as its type and the amount of free space. Each Drive
object contains a single Folder object
representing the drives top-level folder, or root. Each Folder
object contains a Folders collection and a Files
collection. The Folders collection contains a Folder
object for each subfolder within the folder, and the Files
collection contains a File object for each file
in the folder.
The Drives, Folders,
and Files collections are like any other Visual
Basic collection, and they are used the same way. (I cant
explain collections here, but its a good idea for you to
understand them because they are used a lot in Visual Basics
objects.)
Each Drive object has a set of
properties (listed in Table 3) that provides information about
the physical drive. Except as noted, these properties are all
read-only.
Table 3. Drive object
properties.
| Property |
Description |
| AvailableSpace |
The amount of space available to a user on the
specified drive or network share. Generally the same as
the FreeSpace property, but may differ
on systems that support quotas. |
| DriveLetter |
The drive letter associated with the drive. Returns a
zero-length string for network drives that have not been
mapped to a drive letter. |
| DriveType |
A value indicating the type of the drive. Possible
values are 0 (unknown), 1 (removable), 2 (fixed), 3
(network), 4 (CD-ROM), and 5 (RAM disk). |
| FileSystem |
The type of file system. Available return types
include FAT, NTFS, and CDFS. |
| FreeSpace |
The amount of space available to a user on the
specified drive or network share. Generally the same as
the AvailableSpace property, but may
differ on systems that support quotas. |
| IsReady |
Returns True if the drive is ready, False
if not. Used with removable media and CD-ROM drives,
returning False if the media has not
been inserted. |
| Path |
The path of the drive. This consists of the drive
letter followed by a colon. |
| RootFolder |
Returns a Folder object representing
the drives root path. |
| SerialNumber |
The unique serial number identifying a disk. Use this
property to verify that a removable media drive contains
the proper media. |
| ShareName |
The share name assigned to a network drive. For
non-network drives, a zero-length string. |
| TotalSize |
The total capacity of the drive. |
| VolumeName |
The volume name of the drive. You can write to this
property to change a drives volume name. |
|
A simple program can demonstrate how to use the
Drives collection to obtain information about
the drives on the system. Create a Standard EXE project and place
a Text Box on the form. Set the Text Boxs Multiline
property to True, and set its size to nearly
fill the form. Put the code from Listing 1 in the Text Boxs
Click event procedure. When you run the program,
click on the Text Box control to display a list of the systems
drives and their total and free space.
The Folder Object
A Folder object represents a single folder, or
subdirectory, on a drive. You use the objects methods to
copy, move, or delete the folder (as explained below), and you
use the objects properties to obtain information about the
folder. Perhaps most important, a Folder object
contains two collections, Files and SubFolders,
that provide access to the files and subfolders within the
folder. Table 4 explains the properties of the Folder
object.
Table 4. Properties of the Folder
object.
| Property |
Description |
| DateCreated |
Date and time the folder was created. |
| DateLastAccessed |
Date and time the folder was last accessed. |
| DateLastModified |
Date and time the folder was last modified. |
| Drive |
Drive letter of the drive where the folder resides. |
| Files |
A Files collection containing all
the files in the folder. |
| IsRootFolder |
True if the folder is the root, False
otherwise. |
| Name |
Sets or returns the name of the folder. |
| ParentFolder |
Returns a Folder object representing
the folders parent folder. |
| Path |
The path of the folder, including drive letter. |
| ShortName |
The short name used by programs that require the old
8.3 naming convention. |
| ShortPath |
The short path used by programs that require the old
8.3 naming convention. |
| Size |
The size, in bytes, of all files and subfolders
contained in the folder. |
| SubFolders |
A Folders collection containing one Folder
object for each subfolder. |
|
Because each Folder object
contains information about its parent folder and its subfolders,
you can easily traverse the entire folder structure on a drive.
This is a powerful tool, as will be demonstrated later. First,
however, lets look at the Folder objects
methods.
The Copy method copies the
folder and its contents to a new location. The syntax is as
follows (assuming f to be a Folder object):
f.Copy destination[, overwrite]
The destination argument
specifies the destination where the folder is to be copied to.
Set overwrite to True (the
default) to overwrite existing files or folders, or to False
otherwise. Note that you can also copy a folder using the FileSystemObjects
CopyFolder method.
The Move method moves the
folder and its contents from one location to another. The syntax
is:
f.Move destination
Here, destination specifies
the destination where the folder is to be moved to. You can also
move folders with the FileSystemObjects MoveFolder
method.
The Delete method deletes a
folder and its contents. The syntax is:
f.Delete [force]
The optional force argument
specifies whether files or folders with the read-only attribute
set should be deleted (force = True) or not (force
= False, the default). You can also delete folders with
the FileSystemObjects DeleteFolder
method.
To demonstrate the power of the Folder
object, I created a small utility that counts the total number of
files and folders on your C drive. This might seem like a
difficult task, but it requires relatively little code. The
simplicity of this program is a result of two things: the design
of the Folder object and the use of a recursive
algorithm. Heres an outline of how it works:
- Get the drives root Folder
object.
- Use the root folders Folders
collection to access each of its subfolders.
- Determine the number of files and
subfolders in each subfolder, and add these values to the
totals.
- Use the subfolders Folders
collection to access each of its subfolders.
- Continue until all subfolders have been
processed.
Create a standard EXE project with a single
form. Place one Label control and a control array of two Command
Buttons on the form. Set the Labels Caption
property to a blank string, and the Command Buttons Caption
properties to Start and Quit. Place the
following global variable declarations in the General section of
the forms code:
Dim NumFolders As Long, NumFiles
As Long
These variables will hold the counts of files
and folders. Generally speaking, its not good programming
practice to use global variables such as these, but for such a
simple program, it simplifies our job and will not cause any
problems. Next, place the code shown in Listing 2 in the Command
Buttons Click event procedure. When the
user clicks on the Start button, this code does the following:
- Initializes the counter variables to 0.
- Disables the Command Buttons so they
cannot be clicked while the counting process is in
progress.
- Displays Working
in the
Label control.
- Calls the procedure CountFilesAndFolders
(yet to be written) to perform the count.
- When execution returns from the procedure,
re-enables the Command Buttons.
The process of counting the files and folders
is performed by the procedure CountFilesAndFolders.
To be more accurate, the counting process is started by this
procedure. The code is shown in Listing 3. Heres what the
code does:
- Creates a FileSystemObject.
- Loops through the Drives
collection until drive C: is found.
- Passes the drives RootFolder,
which youll remember is a Folder
object, to the procedure DoCount.
The real work of the program is done by the DoCount
procedure, shown in Listing 4. Given how much work it does, it is
deceptively short. It is here that the power of the recursive
algorithm comes into play. DoCount is passed a Folder
object as its argument. Then, heres what it does:
- Gets the number of subfolders in the
folder and adds it to the folders count.
- Gets the number of files in the folder and
adds it to the files count.
- Calls DoCount for each
subfolder in the Folders collection.
Step 3 is where the recursion occurswhen
the DoCount procedure calls itself. As this
program illustrates, recursion can be a powerful technique for
certain tasks. If you dont believe me, try to write a
program that counts the files and folders on a drive without
using recursion.
The File Object
Now lets turn our attention to the final
member of the FSO team, the File object. In the
FSO model, each file on a disk is represented by a File
object. There are two ways to create a File
object. If you know the name and path of the file, you can use
the FileSystemObjects GetFile
method. Assuming that fs is an instance of the FileSystemObject
class:
Dim f
Set f = fs.GetFile(filespec)
The argument filespec contains
the filename, including a relative or absolute path. An error
occurs if the file called out in filespec does
not exist. Note that executing GetFile does not
open the file, it simply returns a File object
linked to the file.
Another way to obtain a File
object is from a Folder objects Files
collection. As you learned earlier, you can create a Folder
object for any subfolder on a disk, and the Folder
object contains a Files collection containing
one File object for each file in the folder. You
can write code to iterate through the collection, looking for one
or more files that meet a specified criterion. For example, the
following code creates an array of File objects
containing all the DLL files in the applications current
path:
Dim fs, f, f1, filelist()
Dim i As Integer, j As Integer
i = 0
ReDim filelist(0)
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFolder(App.Path)
For Each f1 In f.Files
If LCase(Right(f1.Name, 3)) = "dll" Then
i = i + 1
ReDim Preserve filelist(i)
Set filelist(i) = f1
End If
Next
Once you create a File object,
you have access to all the properties of the file. You can also
use the objects methods for certain types of file
manipulation. The methods and properties are explained in Tables
5 and 6.
Table 5. The File
objects methods.
| Method |
Description |
| Copy dest [, overwrite] |
Copies the file to dest. An existing
file is overwritten only if overwrite is
True (the default). |
| Move dest |
Moves the file to dest. |
| Delete [force] |
Deletes the files. Read-only files are deleted only
if force is True. The
default is False. |
| OpenAsTextStream |
Opens the file and returns a TextStream
object. |
Table 6. The File
objects properties.
| Property |
Description |
| Attributes |
Returns a value summarizing the files
attributes, as explained in detail below. |
| DateCreated |
Date and time the file was created. |
| DateLastAccessed |
Date and time the file was last accessed. |
| DateLastModified |
Date and time the file was last modified. |
| Drive |
Drive letter of the drive where the file resides. |
| Name |
Sets or returns the name of the file. |
| ParentFolder |
Returns a Folder object representing
the files parent folder. |
| Path |
The path of the file, including drive letter. |
| ShortName |
The short filename used by programs that require the
old 8.3 naming convention. |
| ShortPath |
The short path used by programs that require the old
8.3 naming convention. |
| Size |
The size, in bytes, of the file. |
| Type |
Returns information about the type of the file. |
|
The Attributes property
provides information about the files attributes, such as
whether it is read-only or a system file. The single value
returned by the Attributes property is a
composite of the individual attribute values, as shown in Table
7. This table also indicates which of the individual attributes
are read/write and which are read-only. You use Visual Basics
logical operators to convert between individual file attributes
and the value of the Attributes property.
Table 7. Component values of the Attribute
property.
| Attribute |
Value |
Description |
Access |
| Normal |
0 |
Normal file; no attributes are set |
|
| ReadOnly |
1 |
Read-only file |
Read/write |
| Hidden |
2 |
Hidden file |
Read/write |
| System |
4 |
System file |
Read/write |
| Volume |
8 |
Disk drive volume label |
Read-only |
| Directory |
16 |
Folder or directory |
Read-only |
| Archive |
32 |
File has changed since last backup |
Read/write |
| Alias |
64 |
Link or shortcut |
Read-only |
| Compressed |
128 |
Compressed file |
Read-only |
|
Even though it will take a lot of getting used
to, the FSO approach to file access and management is a great
improvement over the old methods. Once FSO is expanded to include
random access and binary files, youll be able to relegate
the traditional Basic file-related statements to the dustbin of
history.
Listings
The code listings for this article can be found at http://www.pgacon.com/BVColumns/BV16.HTM
During daylight hours, Peter is a research
scientist at Duke University Medical Center in Durham, North
Carolina. Comments and suggestions may be sent to him at paitken@acpub.duke.edu
Copyright © 1998 The Coriolis Group, LLC. All rights reserved.
|
©Aivosto Oy
-
|