Web Developer 2

File Manipulation with ASP

The FileSystemObject

Manipulating files is something that most computer programs do.  ASP applications make use of the Scripting.FileSystemObject (FSO) to manipulate files and folders and read and write text files.  The FSO provides a rich API to process files and folders.

The FSO includes an object model consisting of the following objects/collections

Object/Collection

Description

FileSystemObject

Main object. Contains methods and properties that allow you to create, delete, gain information about, and generally manipulate drives, folders, and files. Many of the methods associated with this object duplicate those in other FSO objects; they are provided for convenience.

Drive

Object. Contains methods and properties that allow you to gather information about a drive attached to the system, such as its share name and how much room is available. Note that a "drive" isn't necessarily a hard disk, but can be a CD-ROM drive, a RAM disk, and so forth. A drive doesn't need to be physically attached to the system; it can be also be logically connected through a network.

Drives

Collection. Provides a list of the drives attached to the system, either physically or logically. The Drives collection includes all drives, regardless of type. Removable-media drives need not have media inserted for them to appear in this collection.

File

Object. Contains methods and properties that allow you to create, delete, or move a file. Also allows you to query the system for a file name, path, and various other properties.

Files

Collection. Provides a list of all files contained within a folder.

Folder

Object. Contains methods and properties that allow you to create, delete, or move folders. Also allows you to query the system for folder names, paths, and various other properties.

Folders

Collection. Provides a list of all the folders within a Folder.

TextStream

Object. Allows you to read and write text files.

As you can see, the FSO contains abstractions for drives, folders, and files.  You can access either a collection of each type of object or individual objects in a given collection based on your application’s needs.  Note also that the FSO provides access to a TextStreamObject.  You can use the TextStream object to read and write text files in your applications.

Working with Drives and Folders

The FSO allows you to interact with the File system of the server programmatically.  With the FSO, you can get information about drives, files, and folders, create and delete files and folders, and copy and move files and folders.  Note that Drives are essentially read-only abstractions – for obvious reasons.  You really wouldn’t want the ability to delete a drive from your server, would you?

Working with Drives

The Drive object allows you to gain information about the various drives attached to a system, either physically or over a network. Its properties allow you to obtain information about:

 

Here’s a function that gets information from a drive:

function ShowDriveInfo1(drvPath)

{

   var fso, drv, s ="";

   fso = Server.CreateObject("Scripting.FileSystemObject");

   drv = fso.GetDrive(fso.GetDriveName(drvPath));

   s += "Drive " + drvPath.toUpperCase()+ " - ";

   s += drv.VolumeName + "<br>";

   s += "Total Space: " + drv.TotalSize / 1024;

   s += " Kb" + "<br>";

   s += "Free Space: " + drv.FreeSpace / 1024;

   s += " Kb" + "<br>";

   Response.Write(s);

}

 

As you can see, accessing a drive is actually pretty simple.  First, instantiate the FSO.  Then call the GetDrive() method on the FSO passing in a string representation of a drive (i.e. “c:\”).  The function above then makes use of some of the properties of the drive object to build a display string.  The display string outputs the drive letter, volume name, used space, and free space.

Working with Folders

Following are some common tasks involving working with folders and the associated methods of the Folder and FSO objects:

Task

Method

Create a folder.

FileSystemObject.CreateFolder

Delete a folder.

Folder.Delete or FileSystemObject.DeleteFolder

Move a folder.

Folder.Move or FileSystemObject.MoveFolder

Copy a folder.

Folder.Copy or FileSystemObject.CopyFolder

Retrieve the name of a folder.

Folder.Name

Find out if a folder exists on a drive.

FileSystemObject.FolderExists

Get an instance of an existing Folder object.

FileSystemObject.GetFolder

Find out the name of a folder's parent folder.

FileSystemObject.GetParentFolderName

Find out the path of system folders.

FileSystemObject.GetSpecialFolder

You may have noticed that some of the methods are called from the Folder object and some from the FSO.  It makes sense when you consider the activities of these methods.  You wouldn’t want a Folder object to be able to delete itself for example.  Rather, the Delete() method of the Folder object deletes child Folders of the current folder.  This is merely a convenience as you could have built a path to the Folder object you’d like to delete and then called DeleteFolder() from the FSO.  The same is true for moving and copying Folder objects.

 

Following is an example of getting information from, creating, and removing Folder objects:

 

function ShowFolderInfo()

{

   var fso, fldr, s = "";

   // Get instance of FileSystemObject.

   fso = Server.CreateObject("Scripting.FileSystemObject");

   // Get Drive object.

   fldr = fso.GetFolder("c:"); //assumes the server has a ‘c:’ drive

   // Print parent folder name.

   Response.Write("Parent folder name is: " + fldr + "<br>");

   // Print drive name.

   Response.Write("Contained on drive " + fldr.Drive + "<br>");

   // Print root file name.

   if (fldr.IsRootFolder)

     Response.Write("This is the root folder.");

   else

     Response.Write("This folder isn't a root folder.");

   Response.Write("<br><br>");

   // Create a new folder with the FileSystemObject object.

   fso.CreateFolder ("C:\\Bogus");

   Response.Write("Created folder C:\\Bogus" + "<br>");

   // Delete the newly created folder.

   fso.DeleteFolder ("C:\\Bogus");

   Response.Write("Deleted folder C:\\Bogus" + "<br>");

}

 

Displaying the objects contained within a Folder object is also rather easy.  First, get a handle to a Folder object.  Then, wrap an Enumerator around one of the child collections and loop through it processing each item in the enumerator until you run out of items.  An Enumerator is essentially a list of the same type of objects that includes methods that make it easy to move through the list.  Hre’s an example function that lists sub-folders of a given folder:

 

function ShowSubFolders(fldr)

{

   var fso, f, fEnum, s;

   fso = Server.CreateObject("Scripting.FileSystemObject");

   f = fso.GetFolder(Server.MapPath(fldr));

   fEnum = new Enumerator(f.SubFolders);

   fEnum.moveFirst();

   s = "";

   while (!fEnum.atEnd())

   {

      s += fEnum.item();

      s += "<br>";

      fEnum.moveNext();

   }

   return(s);

}

 

You can use the above code to list all of the sub-folders of a given folder by passing a reference to that folder as an argument to the function.  Here’s an example that lists all of the files in a folder using the same mechanism:

 

function showFiles(folderspec){

   var fso, f, fc, s, file;

   fso = Server.CreateObject("Scripting.FileSystemObject");

   f = fso.GetFolder(Server.MapPath folderspec));

   fc = new Enumerator(f.files);

   fc.moveFirst();

   s = "";

   while(!fc.atEnd()){

      file = fc.item();

      s += '<a href="’ +  file.Name + '">' + file.Name + '</a><br>\n';

      fc.moveNext()

   }

      return(s);

}

 

The showFiles() method is quite useful – especially in a web environment.  I’ve used the showFiles() method to enable document repositories.  In other words, I can simply dump documents into a directory, regardless of their type, and list them with the showFiles() method.  This is especially useful for things like forms or committee minutes.  I just place the documents in the folder and they are instantly accessible.

Working with  Files

Moving, Copying, and Deleting Files

The FSO has 2 methods each for moving, copying, and deleting files:

Task

Method

Move a file

File.Move or FileSystemObject.MoveFile

Copy a file

File.Copy or FileSystemObject.CopyFile

Delete a file

File.Delete or FileSystemObject.DeleteFile

Following is an example that makes use of the above methods:

 

function ManipFiles()

{

   var fso, f1, f2, s;

   fso = new ActiveXObject("Scripting.FileSystemObject");

   f1 = fso.CreateTextFile("c:\\testfile.txt", true);

   Response.Write("Writing file <br>");

   // Write a line.

   f1.Write("This is a test.");

   // Close the file to writing.

   f1.Close();

   Response.Write("Moving file to c:\\tmp <br>");

   // Get a handle to the file in root of C:\.

   f2 = fso.GetFile("c:\\testfile.txt");

   // Move the file to \tmp directory.

   f2.Move ("c:\\tmp\\testfile.txt");

   Response.Write("Copying file to c:\\temp <br>");

   // Copy the file to \temp.

   f2.Copy ("c:\\temp\\testfile.txt");

   Response.Write("Deleting files <br>");

   // Get handles to files' current location.

   f2 = fso.GetFile("c:\\tmp\\testfile.txt");

   f3 = fso.GetFile("c:\\temp\\testfile.txt");

   // Delete the files.

   f2.Delete();

   f3.Delete();

   Response.Write("All done!");

}

 

The above creates a text file in the root directory of drive C, writes some information to it, moves it to a directory called \tmp, makes a copy of it in a directory called \temp, then deletes the copies from both directories.

 

To run the following example, create directories named \tmp and \temp in the root directory of drive C:

Accessing File Properties

In addition to manipulation, you can get information form files through the File object’s properties.  Following is an example that displays information about a File:

 

function ShowFileAccessInfo(filespec)

{

   var fso, f, s;

   fso = Server.CreateObject("Scripting.FileSystemObject");

   f = fso.GetFile(filespec);

   s = f.Path.toUpperCase() + "<br>";

   s += "Created: " + f.DateCreated + "<br>";

   s += "Last Accessed: " + f.DateLastAccessed + "<br>";

   s += "Last Modified: " + f.DateLastModified  

   return(s);

}

 

You can use the above function to alert users when files have changed.  It’s an easy way to let your users know when something new happens.

Reading and Writing Files

Creating and Opening Text Files

There are three ways to create an empty text file (sometimes referred to as a "text stream").

 

The first way is to use the CreateTextFile method. The following example demonstrates how to create a text file using the CreateTextFileMethod method.

 

var fso, f1;

fso = Server.CreateObject("Scripting.FileSystemObject");

f1 = fso.CreateTextFile("c:\\testfile.txt", true);

 

The second way to create a text file is to use the OpenTextFile method of the FileSystemObject object with the ForWriting flag set.

 

var fso, ts;

var ForWriting= 2;

fso = Server.CreateObject("Scripting.FileSystemObject");

ts = fso.OpenTextFile("c:\\test.txt", ForWriting, true);

 

A third way to create a text file is to use the OpenAsTextStream method with the ForWriting flag set.

 

var fso, f1, ts;

var ForWriting = 2;

fso = Server.CreateObject("Scripting.FileSystemObject");

fso.CreateTextFile ("c:\\test1.txt");

f1 = fso.GetFile("c:\\test1.txt");

ts = f1.OpenAsTextStream(ForWriting, true);

Writing to the File

Once the text file is created, add data to the file using the following three steps:

 

  1. Open the text file.

  2. Write the data.

  3. Close the file.

 

To open an existing file, use either the OpenTextFile method of the FileSystemObject object or the OpenAsTextStream method of the File object.

 

To write data to the open text file, use the Write, WriteLine, or WriteBlankLines methods of the TextStream object, according to the tasks outlined in the following table.

Task

Method

Write data to an open text file without a trailing newline character.

Write

Write data to an open text file with a trailing newline character.

WriteLine

Write one or more blank lines to an open text file.

WriteBlankLines

 

To close an open file, use the Close method of the TextStream object.

 

Note   The newline character contains a character or characters (depending on the operating system) to advance the cursor to the beginning of the next line (carriage return/line feed). Be aware that the end of some strings may already have such nonprinting characters.

 

The following example demonstrates how to open a file, use all three write methods to add data to the file, and then close the file:

 

function CreateFile()

{

   var fso, tf;

   fso = Server.CreateObject("Scripting.FileSystemObject");

   tf = fso.CreateTextFile("c:\\testfile.txt", true);

   // Write a line with a newline character.

   tf.WriteLine("Testing 1, 2, 3.") ;

   // Write three newline characters to the file.

   tf.WriteBlankLines(3) ;

   // Write a line.

   tf.Write ("This is a test.");

   tf.Close();

}

 

Reading Files

To read data from a text file, use the Read, ReadLine, or ReadAll method of the TextStream object. The following table describes which method to use for various tasks.

Task

Method

Read a specified number of characters from a file.

Read

Read an entire line (up to, but not including, the newline character).

ReadLine

Read the entire contents of a text file.

ReadAll

If you use the Read or ReadLine method and want to skip to a particular portion of data, use the Skip or SkipLine method. The resulting text of the read methods is stored in a string which can be displayed in a control, parsed by string functions (such as Left, Right, and Mid), concatenated, and so forth.

 

The following example demonstrates how to open a file, write to it, and then read from it:

 

function ReadFiles()

{

   var fso, f1, ts, s;

   var ForReading = 1;

   fso = new ActiveXObject("Scripting.FileSystemObject");

   f1 = fso.CreateTextFile("c:\\testfile.txt", true);

   // Write a line.

   Response.Write("Writing file <br>");

   f1.WriteLine("Hello World");

   f1.WriteBlankLines(1);

   f1.Close();

   // Read the contents of the file.

   Response.Write("Reading file <br>");

   ts = fso.OpenTextFile("c:\\testfile.txt", ForReading);

   s = ts.ReadLine();

   Response.Write("File contents = '" + s + "'");

   ts.Close();

}

 

Shared Files

Although the FSO provides a robust API for ASP applications, be aware that it doesn’t perform magic!  You must still consider, for example, the issue if sharing files between multiple users – especially those files accessed through a web application.

 

Here’s a scenario illustrating how difficult it can be to manage files within a web application:

 

Suppose you have 2 users who wish to write to the same file.  User 1 opens the file for writing.  Then user 2 opens the file for writing.  User 1’s phone rings, she answers, talks for a while, then hangs up.  She’s now ready to work with the file.  User 2, however, has already completed his writing to the file while user 1 was on the phone.  So, an  interesting situation arises: user 1 is looking at stale data.  Even worse, when user1 saves her changes, they’ll overwrite user 2’s data!

 

So, how do you eliminate these kinds of problems?  Well, the answer to that one isn’t so easy.  You could lock the application while user1 has the file open.  That’s not very economical nor friendly as user 2 will be blocked from completing his task while the application is locked.

 

A better idea would be to check the attributes of the file to be written before it is written.  That way you could check whether or not to simply write the file or merge the two edits together.  Of course, you’d then need to write your own merge routine (sounds difficult but really isn’t – just append to the end rather than overwrite).  Still, that could add up to more work than is necessary.

 

In short, there is no easy answer to the problem of shared resources.  Just make sure that you take into account the issues when designing your applications.