Reading and Writing Text Files

Microsoft® Windows® 2000 Scripting Guide

One of the more powerful tools available to system administrators is the text file. This might seem hard to believe in an age of high-resolution graphics and multi-user databases. Nevertheless, simple text files, such as those created in Notepad, remain a key element in system administration. Text files are lightweight and low maintenance: They use up very little disk space and require no additional software of any kind to be installed on the computer. Text files are easy to work with and are extremely portable: A text file created by using a script can be copied and viewed on almost any computer in the world, including computers that do not run a Windows operating system.

In addition to their convenience, text files provide a quick, easy, and standardized way to get data both into a script and out of a script. Text files can be used to hold arguments that would otherwise need to be typed at the command line or hard-coded into a script; rather than typing 100 server names at the command line, a script can simply read those names from a text file. Likewise, text files provide a quick and easy way to store data retrieved from a script. This data could be written directly to a database; however, that requires additional configuration on the server, additional coding in the script, and additional overhead when the script runs. Instead, data can be saved to a text file and then later imported into a database.

The FileSystemObject provides a number of methods for both reading from and writing to text files.

Creating Text Files

The FileSystemObject allows you to either work with existing text files or create new text files from scratch. To create a brand-new text file, simply create an instance of the FileSystemObject and call the CreateTexFile method, passing the complete path name as the method parameter.

For example, the script in Listing 4.32 creates a new text file named ScriptLog.txt in the C:\FSO folder.

Listing 4.32 Creating a Text File

  
1
2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("C:\FSO\ScriptLog.txt")

If the file does not exist, the CreateTextFile method creates it. If the file does exist, the CreateTextFile method will overwrite the existing file and replace it with the new, blank file. If you prefer that the existing file not be overwritten, you can include the optional Overwrite parameter. When this parameter is False, existing files are not overwritten; when this parameter is True (the default value), existing files are overwritten. For example, the following code sample does not overwrite the file C:\FSO\ScriptLog.txt if that file already exists:

Set objFile = objFSO.CreateTextFile("C:\FSO\ScriptLog.txt", False)

If you set the Overwrite parameter to False and the file already exists, a run-time error will occur. Because of that, you might want to check for the existence of the file and then, if the file exists, take some other action, such as allowing the user to specify an alternative file name for the new file.

Creating File Names Within the Script

One way to avoid the problems that can occur if a file already exists is to allow the script to generate a unique file name. Because the file name generator does not create meaningful file names, this is probably not a good approach for naming log files and other files that you might need to refer to in the future. However, it does provide a way to ensure unique file names for scripts that require a temporary file. For example, you might have your script save data in HTML or XML format, have that data displayed in a Web browser, and then have this temporary file deleted as soon as the Web browser is closed. In a situation such as that, you can use the GetTempFile name method to generate a unique file name.

To generate a unique file name, a script must create an instance of the FileSystemObject and then call the GetTempName method (with no parameters). For example, the script in Listing 4.33 uses a For Next loop to create 10 random file names.

Listing 4.33 Creating a File Name

  
1
2
3
4
5
Set objFSO = CreateObject("Scripting.FileSystemObject")
For i = 1 to 10
 strTempFile = objFSO.GetTempName
 Wscript.Echo strTempFile
Next

When this script is run under Cscript, output similar to the following appears in the command window:

rad646E9.tmp
radEC50C.tmp
rad0C40A.tmp
radE866E.tmp
rad77F3D.tmp
rad19970.tmp
rad7A21A.tmp
radB9DDC.tmp
rad84930.tmp
rad92199.tmp

note Note

  • The file names generated by GetTempName are not guaranteed to be unique, partly because of the algorithm used to generate the names and partly because there are only a finite number of possible names; file names are limited to eight characters, and the first three characters are always rad. For example, in a test script that created 10,000 file names, one right after another, 9,894 names were unique. The remaining 106 were duplicates (53 pairs of duplicated names).

The demonstration script in Listing 4.34 uses the GetTempName method to create a file. The script must:

  1. Create an instance of the FileSystemObject.

  2. Set a variable named strPath to the folder where the file will be created (C:\FSO).

  3. Use the GetTempName method to generate a unique file name.

  4. Use the BuildPath method to combine the folder name and file name and create a full path for the temporary file. The full path is stored in the variable strFullName.

  5. Call the CreateTextFile method, using strFullName as the method parameter.

  6. Close the file immediately after creating it. In a production environment, you would most likely write data to the file before closing it.

Listing 4.34 Creating and Naming a Text File

  
1
2
3
4
5
6
Set objFSO = CreateObject("Scripting.FileSystemObject")
strPath = "C:\FSO"
strFileName = objFSO.GetTempName
strFullName = objFSO.BuildPath(strPath, strFileName)
Set objFile = objFSO.CreateTextFile(strFullName)
objFile.Close

Opening Text Files

Working with text files is a three-step process. Before you can do anything else, you must open the text file. This can be done either by opening an existing file or by creating a new text file. (When you create a new file, that file is automatically opened and ready for use.) Either approach returns a reference to the TextStream object.

After you have a reference to the TextStream object, you can either read from or write to the file. However, you cannot simultaneously read from and write to the same file. In other words, you cannot open a file, read the contents, and then write additional data to the file, all in the same operation. Instead, you must read the contents, close the file, and then reopen and write the additional data.

When you open an existing text file, the file can be opened either for reading or for writing. When you create a new text file, the file is open only for writing, if for no other reason than that there is no content to read.

Finally, you should always close a text file. Although this is not required (the file will generally be closed as soon as the script terminates), it is good programming practice.

To open a text file:

  1. Create an instance of the FileSystemObject.

  2. Use the OpenTextFile method to open the text file. The OpenTextFile method requires two parameters: the path to the file and one of the following values:

    • For reading (parameter value = 1, constant = ForReading). Files opened in this mode can only be read from. To write to the file, you must open it a second time by using either the ForWriting or ForAppending mode.

    • For writing (parameter value 2, constant = ForWriting). Files opened in this mode will have new data replace any existing data. (That is, existing data will be deleted and the new data added.) Use this method to replace an existing file with a new set of data.

    • For appending (parameter value 8, constant = ForAppending). Files opened in this mode will have new data appended to the end of the file. Use this method to add data to an existing file.

You must use the appropriate parameter when opening the file. For example, if you open a file for reading and then attempt to write to the file, you will receive a "Bad file mode" error. You will also receive this error if you attempt to open anything other than a plain-text file. (It is worth noting that both HTML and XML files are plain-text files.)

You can use either the parameter value (for example, 1 for reading) or you can create a constant and set the value appropriately. For example, both of these methods will open a file for reading:

Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\FSO\ScriptLog.txt", ForReading)
Set objFile2 = objFSO.OpenTextFile("C:\FSO\ScriptLog2.txt", 1)

However, you cannot use the constants without first defining them. This is due to the fact that VBScript does not have intrinsic access to COM object constants. The following script sample will fail and return an "Invalid procedure call or argument" error because the ForReading constant has not been explicitly defined. Because it has not been defined, ForReading is automatically assigned the value 0, and 0 is not a valid parameter for OpenTextFile.

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\FSO\ScriptLog.txt", ForReading)

The script in Listing 4.35 opens C:\FSO\ScriptLog.txt for reading, using the user-defined constant ForReading to represent the value 1.

Listing 4.35 Opening a Text File for Reading

  
1
2
3
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\FSO\ScriptLog.txt", ForReading)

Closing Text Files

Any text files opened by a script are automatically closed when the script ends. Because of this, you do not have to explicitly close text files any time you open them. Nevertheless, it is a good idea to always close text files when you are finished with them. Not only is this good programming practice, but problems will occur if you try to do one of the following without first closing the file:

  • Delete the file. As noted previously in this chapter, you might occasionally write scripts that create a temporary file, use that file for some purpose, and then delete the file before the script terminates. If you attempt to delete an open file, however, you will encounter an "Access denied" error because the operating system will not allow you to delete an open file.

  • Reread the file. There might be times when you need to read the same file multiple times within a script. For example, you might open a text file, save the entire contents of the file to a string variable, and then search that string for the existence of a particular error code. If the code is found, you might then read the file on a line-by-line basis, extracting each line where the error was recorded.

    If you try to read an open file multiple times, however, you either will not receive the expected results or will encounter a run-time error. For example, the following script reads a text file, echoes the contents of that file back to the screen, and then attempts to repeat the procedure:

    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile("C:\FSO\ScriptLog.txt", 1)
    Wscript.Echo "Reading file the first time:"
    strContents = objFile.ReadAll
    Wscript.Echo strContents
    Wscript.Echo "Reading file the second time:"
    Do While objFile.AtEndOfStream = False
        strLine = objFile.ReadLine
        Wscript.Echo strLine
    Loop
    

    When this script is run under Cscript, the following output appears in the command window:

    Reading file the first time:
    File line 1.
    File line 2.
    File line 3.
    Reading file the second time:
    

    The first time the file was read, the contents were stored in the variable strContents. The second time the file was read, however, no data was echoed to the screen. This is because the end of the file had already been reached, and there was no more data left to read. To reread the file, you must close the file and then reopen it. You cannot read to the end of a file and then jump back to the beginning.

The TextStreamObject Close method is used to close a text file. For example, the script shown in Listing 4.36 creates an instance of the FileSystemObject, opens a text file (C:\FSO\ScriptLog.txt), and then immediately closes the file. To access the file contents, you need to call the OpenTextFile method a second time and reopen the file.

Listing 4.36 Opening and Closing a Text File

  
1
2
3
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\FSO\ScriptLog.txt", 1)
objFile.Close