The Wonders of the File System Object

By Chris Payne

Introduction

NOTE:
The computer file system that we’ll be manipulating is
the web server’s. So make sure you have the appropriate
privileges and information (i.e., so you don’t upset your
ISP). Ideally, you’ll have a web server set up on your own
computer so you can test and play.

FSO Model Objects

Drive Object

Provides access to a disk or

network drive

FileSystemObject Object

Provides access to a computer’s file

system

Folder Object

Provides access to all properties of a

folder

TextStream Object

Provides an easy way to access a file’s

contents

You can use the above objects to do nearly anything on a computer,
including wreak havoc – so be careful how you play with the FSO.
In a web environment, it can be very important to store information,
such as user info, log files, etc. The FSO provides a powerful
and easy way to store your data in an efficient manner. In this
article,
we’ll be mainly concentrating on the FileSystemObject
and TextStream Objects.

NOTE:
The FSO is provided by Microsoft, and as such, the results
for its use on non-Microsoft operating systems are questionable
in the least. For non Windows OSes, you probably wouldn’t
be using active server pages anyway, but I still wouldn’t
recommend trying the FSO.


How Do I Use the FSO?




To be able to use the FSO to perform all your dirty work, you must
first create the object. If you’re familiar with creating objects
in ASP pages, then this next line should be no surprise:



<%

Set fso = Server.CreateObject(“Scripting.FileSystemObject”)

%>





We create the FSO here and set the reference to the variable fso.
We can now use the familiar object.method syntax to perform
file system
manipulations. (Check out the

Visual Basic documentation

to learn more about objects and object
oriented programming.) In this case, we can use fso.method
or fso.
property, as we’ll see in upcoming examples.

NOTE:
The FSO model is located in the scripting runtime dll
provided by Microsoft, scrrun.dll. You can reference this dll
in any application that can reference objects, such as
MS Access, Word, and a whole slew of others. This means
you’re not restricted to just using the FSO in an ASP page.


Here is an abridged list of methods available to the
FSO that we will use here to manipulate files:

File Methods

CopyFile

Copies one or more files from one

place to another

CreateTextFile

Creates a file and returns a TextStream

object

DeleteFile

Deletes a file

OpenTextFile

Opens a file and returns a TextStream
object that can be used to read from or append to the file

For a complete list of all the methods and properties of the FSO,
check out

the Microsoft MSDN reference.
Let’s move onto some examples.



Writing Files




Suppose you wanted to create a simple guestbook. You could set up a
database and store
users' information there.
However, if you don't
need the power of a database application, you can save yourself some
money and overhead, and use the FSO to store your information. Not to
mention the fact that your ISP may limit your choice of database
options.


Let's assume you'll collect some user information in a form.
Here's the HTML for a simple
form:



<html>

<body>

<form action=”formhandler.asp” method=”post”>

<input type=”text” size=”10″ name=”username”>

<input type=”text” size=”10″ name=”homepage”>

<input type=”text” size=”10″ name=”Email”>

</form>

</body>

</html>





Let's look at the script in formhandler.asp that will handle
the form:



<%

' Get form info

strName = Request.Form(“username”)

strHomePage = Request.Form(“homepage”)

strEmail = Request.Form(“Email”)

' create the fso object

Set fso = Server.CreateObject(“Scripting.FileSystemObject”)





So far, this should be nothing new. We take the form variables and
assign them to variables for easier use later on. Now comes the fun
part – writing the file:



path = “c:temptest.txt”

ForReading = 1, ForWriting = 2, ForAppending = 8

' open the file

set file = fso.opentextfile(path, ForAppending, TRUE)

' write the info to the file

file.write(strName) & vbcrlf

file.write(strHomePage) & vbcrlf

file.write(strEmail) & vbcrlf

' close and clean up

file.close

set file = nothing

set fso = nothing





As you recall, the OpenTextFile method returns a TextStream object,
which is another object of the FSO model. The TextStream object
exposes

methods

to manipulate a file's content, such as
Write, ReadLine, and SkipLine. The VB constant vbcrlf generates
a line break.

NOTE:

We specify TRUE in the argument list of OpentextFile to
tell the system to create the file if it doesn't already
exist. If the file does not exist, and you do not specify
TRUE, you will generate an ugly error.


Now navigate to c:temp and open test.txt. You should see the following
information:



User's name

User's home page

User's email





Of course those words will be replaced by whatever the user entered
in the form. Now anyone can come along and fill out your guestbook
and their information will be stored in this file.



Reading Files



So now we have some nice user information stored in a file, which
happily works as a simple database. Now suppose a user comes along
and wants to view all your wonderful visitors. We've got to
spit that
information out somehow. Since we don't have a database with
nicely structured columns, we'll have to get clever to output
the results we want.

We know that in the file we just created, the first line is the
user's
name, the second line is their homepage, and the third line is their
email address. Every subsequent user who comes along will also have
their information stored in this way, so that every third line will
contain the same type of information. Knowing that, we can now write
some code to grab the info:



<%

' create the fso object

set fso = Server.Createobject(“Scripting.FileSystemObject”)

path = “c:temptest.txt”

' open the file

set file = fso.opentextfile(path, 1) <– For
reading





Now let's grab each line and format it accordingly:



do until file.AtEndOfStream

Response.write(“Name: ” & file.ReadLine & ” “)

Response.write(“Home Page: ” & file.ReadLine & ” “)

Response.write(“Email: ” & file.ReadLine & “<p>”)

loop

' close and clean up

file.close

set file = nothing

set fso = nothing

%>




NOTE:

We did a very simple output here, but note that you can
place the information wherever and however you like, including
in table cells and forms.



If you've created and written your file properly, this little loop
will properly list everyone in your database. The ReadLine method reads
one line up to the newline character. Subsequent calls to ReadLine
will read the next lines. AtEndOfStream is a property of the
TextStream
object that lets
us know when we've hit the end of the file.


Suppose for some reason we didn't format the file correctly. If a
user only has 2 lines instead of 3 describing their info, then we
will get some errors here. Our loop gets the next 3 lines
in the file and if there are not 3 more lines to be had, your page
will get mad and throw an error like:




Server object error 'ASP 0177 : 800a003e'




at you. So be sure to add some error
checking to make sure you're not skipping or inserting too many
lines.




Permissions




Now that we've covered the basics, we should discuss permissions.
The FSO runs in the user account that created it. In other words,
if someone accesses your page from the internet, then the internet
account created the FSO. If you are logged onto your computer as
the administrator and you access the page, then the administrator
account created it. This is very
important, because certain accounts have certain permissions, and
the FSO requires a lot of permissions in order to function fully.

The internet account (IUSER_MachineName, where MachineName is the name
of the server) generally has only reading privileges. That means
that users will never be able to write to the guestbook file. There
are,
however, several options to skirt around this issue.


The first, and more difficult, would be to require the user to log
on to the server before they fill out the guestbook. However, the
point of a guestbook is to get information from anonymous users, and
to log users on, we'd have to know who they are, so
we'll skip this option and move on.


The second is to create a directory or file that allows the
IUSER_MachineName
account writing privileges. This can open up some potential
security holes,
because anyone who knows the proper directory and some savvy web skills
can write stuff to your server. This is a big no-no. So you want to
make
sure you place the writeable directory in a nice and hidden spot,
and possibly
place it outside of the web directory structure (i.e. in Windows,
place it in a
directory that is outside the inetpub directory)




Searching with the FSO



You may be thinking “Great, so now I know how to write files. I
could've
figured that out myself.” So you want more tough guy? Let's
try building a
search feature for your web site.


The key to building a search engine is recursion. If you don't
know
what recursion is, find out

why it's cool.

Basically, you write one piece of code that performs a search on
the files in a directory, and then make that same code loop through
all the subdirectories. Since we don't know ahead of time how many
subdirectories there may be, we have to call this piece of code over
and over again until we're through. Recursion in it's
finest.


So let's build the search page. We'll assume that
you've already
built an HTML form for a user to input a search string.



Dim objFolder

Dim strSearchText

Dim objFSO

strSearchText = Request.Form(“SearchText”) <– The
search string

' create the FSO and Folder objects

Set fso = Server.CreateObject(“Scripting.FileSystemObject”)

Set objFolder = objFSO.GetFolder(Server.MapPath(“/”))

Search objFolder





The above code simple initializes variables and gets us started.
The meat of the search is performed by the Search function,
described below:



Function Search(objFolder)

Dim objSubFolder

'loop through every file in the current
folder

For Each objFile in objFolder.Files

Set objTextStream = objFSO.OpenTextFile(objFile.Path,1) <– For Reading

'read the file's contents into a
variable

strFileContents = objTextStream.ReadAll

'if the search string is in the file, then
write a link

' to the file

If InStr(1, strFileContents, strSearchText, 1) then

Response.Write “<A HREF=””/” & objFile.Name & _

“””>” & objFile.Name & “</A><BR>”

bolFileFound = True

End If

objTextStream.Close

Next

'Here's the recursion part – for each

' subfolder in this directory, run the Search function again

For Each objSubFolder in objFolder.SubFolders

Search objSubFolder

Next

End Function




NOTE:

To be able to open files, the FSO requires the actual
path to the file, not the web path. For instance,
c:inetpubwwwroottempindex.html,
not www.enfused.com/temp/index.html or /temp/index.html. To
convert
the latter to the former, we use Server.MapPath(“filename”),
where filename represents the web path.


The code above will run through every subdirectory of every folder
under the initial folder that you specified, which in this case,
would be the root web path, specified by “/”. Then we simply open
each file in the directory, see if the desired string is in that file
and display a link to that file if the search string is found. Not
bad, huh?


Note that as the number of files and subdirectories increases,
so will the time it takes to run this search. It's recommended
that
if you need a heavy duty search feature, turn to something else,
such as Microsoft's Index Server.




Content Management with the FSO




By now, you should have a good taste of the FSO and its methods and
properties. Let's dig a little deeper and do some engineering
design to
tackle a more difficult problem.


Content management is being able to keep track of, manipulate, and
generally perform tasks with content, typically documents in a web
environment. Smart content management does all that in an easy,
painless
fashion. Behind the scenes
of such an application is heavy duty file manipulation. Once again,
enter the FSO. We need to be able to move, delete, rename, and create
files, and our friend the FSO steps in nicely. In the article
above, we
discuss a submission system for writers to
publish their content. What we don't mention is exactly what
to do with
the file once it's up.


First of all, you'll most likely want to rename the file,
since the writer
probably named it something only he would understand or care about.
To be able to keep track of all your documents, you'll want to
rename it
to something unique, that is easily identifiable by your system.
Unfortunately,
the FSO doesn't allow for an easy file renaming, so we'll
have to engineer
a bit.



<%

' create the fso object

set fso = Server.Createobject(“Scripting.FileSystemObject”)

path = “c:temptest.txt”

strDate = Replace(Date(), “/”, “”)

strDir = “c:inetpubwwwrootarticles” & strDate

strNewFileName = Hour(Now) & “_” & Minute(Now) & “_” &

second(Now) & “.html”

' open the old file

set file = fso.opentextfile(path, 1) <– For
reading

strText = file.readall

set file = nothing

' check for and/or create folder

if not fso.folderexists(Server.MapPath(strDir)) then

set f = fso.CreateFolder(Server.MapPath(strDir))

else

set f = fso.GetFolder(Server.MapPath(strDir))

end if

' create and write new file

set file = fso.Createtextfile(f.path & “” & strNewFileName)

file.write(strText)

set f = nothing

file.close

set file = nothing

' delete the old file

fso.DeleteFile(path & “” & rst(“FileName”) & i)

' clean up

set fso = nothing

%>





The lack of the FSO's abilities however can be used to our
advantage here;
we can perform two steps in one. First, we open and read the
file's contents.
I'll assume that we'll want to create a unique folder, as
well as a unique
filename to store the article in. However, since this folder's
path will
change every day, we'll have to first check to see if the folder
already exists, and if it doesn't, create it. This is done by the
if not fso.folderexists section. We then get that path
and use
it to create the new file (you'll recall that the FSO needs
the full path
name to manipulate files, and the GetFolder and
CreateFolder

methods return just that – a full path). After we're done with
the new file,
we'll want to get rid of the old one,
so it doesn't clutter up our file system. This is accomplished
with
fso.DeleteFile.


So the two steps we accomplished here were renaming the file, and
moving
it to a more apropos directory. Note that we could also have done some
more manipulation here, such as editing the text before we wrote it to
the new file.




What You Can't Do



The FSO does have some weaknesses – for instance, it stumbles on
binary files. This includes MS Word documents, many image formats,
and, unfortunately, a lot of other files. You can still, however
otherwise manipulate these files – move them, delete them, etc. What
you can't do is open, read, or write to them. Given some
ingenuity,
a method could be devised to use the FSO to play with binary files,
but many will find it easier to simply use the old Open method.


Another limitation is file size. When you read or write a lot of
content at once, all the information is stored in memory – and the
larger your content, the larger the memory usage. This tends to slow
everything down, so if you need to manipulate really large files,
or a ton of smaller files, consider breaking the files down into
smaller pieces and clearing the memory often (setting your variables
equal to NULL or “”, and releasing your objects ASAP). Moving your
application into a COM object would also tremendously speed up the
process.


You also can't manage permissions and file and folder attributes
with the FSO. A great way to implement security would be to create
the guestbook file we described earlier as read-only, and then change
the attribute to writeable only when we need it, and immediately
change it back. This method is often used in
CGI and
Perl

scripts,
but unfortunately, there's no pleasant way to do this with the
FSO.


What else can I do?


There are a lot of really cool features in the FSO model that most
people
aren't aware of. These are the type of features that you
normally find
out about after you did things the hard way, and you end up
saying “If only I knew that before!”

I'll briefly list the not-so-common but cool functions here.

Little Known FSO Features

GetSpecialFolder Method

Returns the path to a special
Windows folder: the Windows installation folder; the system folder;
and the Windows Temporary folder. Syntax: FSO.GetSpecialFolder([0,
1, or 2])

GetTempName Method

Returns a randomly generated temporary
file or folder name. Useful when you need to store temporary
data (i.e. when you run into the file size limitation described
above).

GetAbsolutePathName Method

Returns the absolute path of a folder (similar
to Server.MapPath). For example, FSO.GetAbsolutePathName(“region”) will
return something like “c:mydocsmyfolderregion”

GetExtensionName Method

Returns the extension for the last item
in a path (i.e. FSO.GetExtensionName(“c:docstest.txt”) will
return txt)

GetBaseName and GetParentFolder Methods

Returns the base and parent folder name
respectively of last item in a path (i.e. FSO.GetParentFolder
(“c:docsmydocs”)
will return 'docs')

Drives Property

Returns a collection of all the drive
objects available on the local machine. This is helpful if you
ever want to build an explorer type interface.



You'll want to make sure you build in robust error handling
routines
though, because some of these above functions will return nasty
errors if the specified file or folder does not exist.




Conclusion



As we can see, the FSO is very nifty, and we only touched the tip
of the 'berg here. Many of these features
are implemented on big-name sites, and
many of them pay big bucks for applications that can do this
type of thing. Meanwhile the little 'ol FSO sits by and waits
for someone to come across and use his power! Um..whoops, did I
say that aloud?


The takeaway here is that you can build very powerful applications
with
the FSO, as well as accomplish some simples tasks more easily. Keep
this one in your
toolbelt!

Happy scripting!


About the Author



Chris Payne Currently lives in the Boston area. He has been building
database driven web sites for
several years. In February 2000, he cofounded Enfused Media, Inc, a web
development/gaming firm.
The first development from EMI was www.enfused.com, a massive gaming portal
for gamers as well
as the gaming business. His offline time is spent with his fiance and
their tropical fish.
Email: [email protected]

More by Author

Must Read