[Previous] [Table of Contents] [Next]

# Accessing Text Files

You can use methods of the FileSystemObject object to read from and write to text files.

## Reading from a Text File

You use the FileSystemObject object's OpenTextFile method to access a text file. Let's look at a simple script that accesses text files. If the script is called without a parameter, it tries to read the file C:\Autoexec.bat. A dialog box allows the user to specify whether the file's content should be shown in a dialog box or in a browser window (Figure 12-12).

Figure 12-12 Content of a text file shown in a browser window and in a dialog box

To read from a text file, you must first create the FileSystemObject object:

    Set fso = CreateObject("Scripting.FileSystemObject")

You should also check whether the file exists because the script causes a run-time error if a file is missing:

    If fso.FileExists(file) Then

If the file exists, you can try to open the file by using the OpenTextFile method of the FileSystemObject object:

    Set txtStream = fso.OpenTextFile(file)

The parameter file, which contains the path (including the name of the text file), must be passed to the method. If the file doesn't exist, a run-time error occurs. The statement above uses only one parameter, which contains the filename. The method supports some optional parameters to control how text files are opened, as shown here:

    Object_name.OpenTextFile(filename[, iomode[, create[, format]]])

This statement has the following parameters:

- filename The name of an existing text file.

- iomode An optional parameter that specifies the I/O mode for the file operation. The parameter can contain the constants ForReading (with a value of 1 for read-only access), ForWriting (with a value of 2 for write access only), and ForAppending (with a value of 8 for write access and appending data at the end of the file).

> NOTE

> You must declare the OpenTextFile constants explicitly in your script because WSH doesn't use predefined names for them. In WSH 2, you can use a .wsf file with a <reference> element that defines a reference to the type library to obtain these constants. (This technique is demonstrated several times in this chapter.)

- create An optional parameter that contains the Boolean value. The value True causes a missing file to be created. The value False doesn't create the file.

- format An optional parameter that specifies the format of the text file to be opened. If the parameter is omitted, an ASCII file is defined for the format. You can set the value to TristateUseDefault (with a value of -2 to open the file with default settings), TristateTrue (with a value of -1 to open the file in Unicode format), and TristateFalse (with a value of 0 to open the file in ASCII format).

To read the lines in a text file, you must apply the ReadLine method to the file object. During reading, you must use the atEndOfStream method to check whether the file's end has been reached. The following loop reads a file line by line into a string:

    Do While Not (txtStream.atEndOfStream)
        Text = Text & txtStream.ReadLine & vbCrLf
    Loop

After you read the file's content, you can use the variable Text for further processing.

The sample script sets C:\Autoexec.bat as the default file. If no other filename is specified, this file is read and its content is shown. It can be helpful, however, if the user can drag another file to the script file's icon so that the script shows the content of the dragged file. You can do this in VBScript by using the following statements:

    file = "C:\Autoexec.bat"        ' Default test file
    ' Try to get a filename from the Arguments collection.
    Set objArgs = WScript.Arguments ' Create object.
    If objArgs.Count > 0 Then       ' Argument found.
        file = objArgs(0)           ' Set filename to first argument.
    End If

After these statements are processed, the variable file contains either the name C:\Autoexec.bat or the path and name of the file dragged to the script's icon. Before you can access the file, you must check whether the file exists:

    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FileExists(file) Then ' Check whether file exists.

    End If

The first line creates a reference to the FileSystemObject object. Then you apply the FileExists method to this object to check whether the file exists. If the file doesn't exist, the script can terminate by using the Quit method. If the script exists, you can read the file's content:

    Set txtStream = fso.OpenTextFile(file) ' Open text file.
    Do While Not (txtStream.atEndOfStream)
        Text = Text & txtStream.ReadLine & vbCrLf
    Loop

The OpenTextFile method opens the file. The sample omits optional parameters because you need only read access. Then it uses a loop to read the file by using the ReadLine method. To test whether the end of the file has been reached, the atEndOfStream method is used. This method returns False if the file's end hasn't been reached. After exiting the loop, the string variable Text contains the entire file. The script then shows the file's content in a simple dialog box or a browser window.

## Pitfalls of Using Dialog Boxes and Browser Windows to View Text Files

To show a simple dialog box in VBScript, you can use this statement:

    WScript.Echo Text

Or you can use a command such as this:

    MsgBox Text, vbOKOnly + vbInformation, Title

If the content of the variable Text contains only a few characters, no problems occur. But if you show the content of a lengthy text file by using the Echo method, the window will be larger than the Desktop. The lower part of the dialog box, which contains the text's trail and the OK button, will be hidden under the taskbar.

Using the VBScript MsgBox call causes a different problem: the text isn't shown in its entirety. The VBScript help says that MsgBox can display a parameter prompt with a maximum length of 1024 characters. If you attempt to show a lengthy text file, however, you see a dialog box that displays only the first part of the file.

The following sample solves this problem by showing a simple dialog box that allows the user to specify a browser window or a dialog box for viewing the file's content (Figure 12-13).

Figure 12-13 Dialog box for selecting the file viewer (browser window or dialog box)

To use Microsoft Internet Explorer to display the content, you can use the following procedure:

    ShowWindow Text, Title

In the samples that follow, the ShowWindow procedure contains the following statements:

    Sub ShowWindow(txt, title)
        Dim oIE, doc1
        ' Create Internet Explorer Application object.
        Set oIE = WScript.CreateObject("InternetExplorer.Application")
        oIE.Navigate "about:blank"  ' Empty HTML document
        oIE.Visible = 1             ' Internet Explorer is visible.
        oIE.ToolBar = 0
        oIE.StatusBar = 0
        ' oIE.Width=600
        oIE.Height = 500
        Do While (oIE.Busy): Loop   ' Important: Wait until Internet
                                    ' Explorer is ready.

        Set doc1 = oIE.Document     ' Get Document object.
        doc1.open                   ' Open document.
        ' Write script into the Document object.
        doc1.writeln "<html><head><title>" & Title & "</title></head>"
        doc1.writeln "<body bgcolor='#FAF0F0'><pre>"
        doc1.writeln txt            ' Text output
        doc1.writeln "</pre></body></html>"
        doc1.close                  ' Close document for write access.
    End Sub

The procedure invokes an Internet Explorer window, writes a valid HTML header, and inserts the content of the submitted string in the browser window. The text itself is formatted using the tags <pre>…</pre>. Then the document is completed with a valid HTML file end (the tags </body></html>). The content of the text file is then shown in a browser window.

Did you notice that the Width property of the browser window isn't set in the procedure? Because the statement to set this property begins with a comment character ('), the browser adjusts the window width based on the length of the lines in the text file.

After implementing the procedure in the sample file, I noticed that some files cause "wrong" results in the browser window. As you can see in Figure 12-14, some lines are shown in bold. Other files (such as HTML files containing forms) are shown as a form in the browser window. I analyzed the HTML source code and found the cause: the ShowWindow procedure simply writes the content of the file to the browser's document window. If the variable Text contains HTML commands embedded in the source code, the browser applies these commands. The results are unpredictable.

Figure 12-14 Text shown in bold in the browser window

For example, if you show a script file that contains statements for writing HTML code to the browser window, these statements affect the browser window. Therefore, you need a "filter" that converts the HTML. First, the tag characters < and > must be converted to &lt; and &gt;.

I decided to write my own filter function, MakeHTMLCode, to convert the string to a format that can be displayed as an HTML document. Besides the tag characters < and >, I decided also to filter all carriage return/line feed codes in the string and convert them to <br> tags so that you can display text in the browser window without inserting all of it into <pre>…</pre> tags. Unfortunately, in HTML a space character is treated as a "white space" character, which means that multiple spaces are stripped off the HTML code and the browser displays only a blank. I then tried to convert the blanks in the string to &nbsp; entities, but the result of several &nbsp; entities in an HTML file depends on the browser used. In Internet Explorer 5, multiple blanks are treated as one blank. I then decided to use a second parameter in the filter function MakeHTMLCode, which controls the filter options. A value of 0 forces the filter to convert all < and > characters. A value of 1 processes the string (as the value 0 does) and converts all line breaks to <br> tags. A value of 2 works like a value of 1 but also forces the filter to convert blanks to &nbsp; entities.

At this point, I'd like to make a few remarks about converting patterns in a string. Version 5 of VBScript and JScript support a regular expression object. You can create this object in VBScript as follows:

    Set oReg = New RegExp

You can then set the properties of this object by using methods such as Replace to convert patterns in a string. If all matches in a string are to be processed, you can set the Global property to True:

     oReg.Global = True

The following command specifies that pattern matching not be case sensitive:

    oReg.IgnoreCase = True

To replace all < characters in a string, you can use the following statements:

    oReg.Pattern = "<"
    txt = oReg.Replace(txt, "&lt;")

The first line sets the pattern, and the second line applies the Replace method to the string txt. The string &lt; is the replacement expression. Here is the entire source code:

    Sub MakeHTMLCode(txt, flag)
        ' Convert text file to HTML structure.
        ' Flag controls which elements are converted.
        ' Use the following values:
        ' 0: Convert all < and > characters to &lt; and &gt;.
        ' 1: Like flag = 0, but also sets vbCrLf to <br> tag
        '    (forces line wrap).
        ' 2: Like flag = 1, but also sets blanks to &nbsp;.
        ' ### Be careful of the order of pattern replacement. ###
        Dim oReg
        Set oReg = New RegExp        ' Create regular expression.
        oReg.Global = True           ' All matches
        oReg.IgnoreCase = True       ' Make case insensitive.

        ' Replace all < with &lt;.
        oReg.Pattern = "<"           ' Set pattern.
        txt = oReg.Replace(txt, "&lt;")

        ' Replace all ">" with "&gt;"
        oReg.Pattern = ">"           ' Set pattern.
        txt = oReg.Replace(txt, "&gt;")

        If flag > 0 Then             ' Replace vbCrLf?
            ' Now we're ready to replace all vbCrLf with <br>.
            oReg.Pattern = vbCrLf       ' Set pattern.
            oReg.Global = True          ' All matches
            txt = oReg.Replace(txt, "<br>")
        End If

        If flag > 1 Then             ' Replace blanks?
            ' Now we're ready to replace all blanks with &nbsp;.
            oReg.Pattern = " "          ' Set pattern.
            oReg.Global = True          ' All matches
            txt = oReg.Replace(txt, "&nbsp;")
        End If
    End Sub

You can use the MakeHTMLCode function to control how the string is filtered. In the sample, the second parameter is set to 0, which forces the filter to simply convert the < and > characters. The carriage return line feed codes remain in the string. Because the text is embedded in <pre>…</pre> tags in the document area, all blanks are unchanged.

The full VBScript implementation is shown in Listing 12-17.

Listing 12-17 ReadTxt.vbs

    '************************************************
    ' File:    ReadTxt.vbs (WSH sample in VBScript)
    ' Author:  (c) G. Born
    '
    ' Reading the content of a text file and
    ' displaying it in a dialog box. The script
    ' uses defaults for "iomode."
    '************************************************
    Option Explicit

    Dim Text, Title
    Dim fso, objArgs                ' Object variables
    Dim txtStream                   ' Text stream
    Dim file                        ' Filename

    file = "C:\Autoexec.bat"        ' Default test file

    ' Try to get a filename from the Arguments collection.
    Set objArgs = WScript.Arguments ' Create object.
    If objArgs.Count > 0 Then       ' Argument found.
        file = objArgs(0)           ' Set filename to first argument.
    End If

    Text = "Content of " & file & vbCrLf & vbCrLf
    Title = "WSH sample - by G. Born"

    ' Create FileSystemObject object to access the file system.
    Set fso = CreateObject("Scripting.FileSystemObject")
    ' Check whether file exists.
    If fso.FileExists(file) Then
        Set txtStream = fso.OpenTextFile(file) ' Open text file.
        Do While Not (txtStream.atEndOfStream)
            Text = Text & txtStream.ReadLine & vbCrLf
        Loop
    Else                  ' Terminate.
        MsgBox "File '" & file & "' not found", _
               vbOKOnly + vbCritical, Title
        WScript.Quit 1    ' Terminate with error code.
    End If

    If MsgBox("Show results in dialog box?", vbYesNo, Title) _
        = vbYes Then    ' Show result in message box.
        MsgBox Text, vbOKOnly + vbInformation, Title
    Else                ' Use browser window for results.
        MakeHTMLCode Text, 0      ' Convert text to HTML (only < and >).
        ShowWindow Text, Title    ' Show result in HTML window.
    End If

    Sub ShowWindow(txt, title)
        Dim oIE, doc1
        ' Create Internet Explorer Application object.
        Set oIE = WScript.CreateObject("InternetExplorer.Application")
        oIE.Navigate "about:blank"  ' Empty HTML document
        oIE.Visible = 1             ' Internet Explorer is visible.
        oIE.ToolBar = 0
        oIE.StatusBar = 0
        'oIE.Width = 600
        oIE.Height = 500

        Do While (oIE.Busy): Loop   ' Important: Wait until Internet
                                    ' Explorer is ready.

        Set doc1 = oIE.Document     ' Get Document object.
        doc1.open                   ' Open document.
        ' Write script to the Document object.
        doc1.writeln "<html><head><title>" & Title & "</title></head>"
        doc1.writeln "<body bgcolor='#FAF0F0'><pre>"
        doc1.writeln txt            ' Text output
        doc1.writeln "</pre></body></html>"
        doc1.close                  ' Close document for write access.
    End Sub

    Sub MakeHTMLCode(txt, flag)
        ' Convert text file to HTML structure.
        ' Flag controls which elements are converted.
        ' Use the following values:
        ' 0: Convert all < and > characters to &lt; and &gt;.
        ' 1: Like flag = 0, but also sets vbCrLf to <br> tag
        '    (forces line wrap).
        ' 2: Like flag = 1, but also sets blanks to &nbsp;.
        ' ### Be careful of the order of pattern replacement. ###
        Dim oReg
        Set oReg = New RegExp        ' Create regular expression.
        oReg.Global = True           ' All matches
        oReg.IgnoreCase = True       ' Make case insensitive.

        ' Replace all < with &lt;.
        oReg.Pattern = "<"           ' Set pattern.
        txt = oReg.Replace(txt, "&lt;")

        ' Replace all ">" with "&gt;"
        oReg.Pattern = ">"           ' Set pattern.
        txt = oReg.Replace(txt, "&gt;")

        If flag > 0 Then             ' Replace vbCrLf?
            ' Now we're ready to replace all vbCrLf with <br>.
            oReg.Pattern = vbCrLf       ' Set pattern.
            oReg.Global = True          ' All matches
            txt = oReg.Replace(txt, "<br>")
        End If

        If flag > 1 Then             ' Replace blanks?
            ' Now we're ready to replace all blanks with &nbsp;.
            oReg.Pattern = " "          ' Set pattern.
            oReg.Global = True          ' All matches
            txt = oReg.Replace(txt, "&nbsp;")
        End If
    End Sub

    '*** End

### The JScript implementation

The following JScript version uses a regular expression object to replace patterns such as < and > with &lt; and &gt;. The JScript exchange method is applied to a text object and requests two parameters. The first parameter must be a regular expression pattern (such as />/ig). The / character encloses the search string; the letter i in ig stands for ignore case, and the g causes a global replace of that pattern in the string object. The second parameter contains the replacement string. The entire JScript version is shown in Listing 12-18.

Listing 12-18 ReadTxt.js

    //************************************************
    // File:    ReadTxt.js (WSH sample in JScript)
    // Author:  (c) G. Born
    //
    // Reading the content of a text file and
    // displaying it in a dialog box
    //************************************************

    var vbYesNo = 4;
    var vbYes = 6;
    var vbInformation = 64;
    var vbQuestion = 32;
    var vbCancel = 2;

    var file = "C:\\Autoexec.bat";
    var Title = "WSH sample - by G. Born";

    // Try to get a filename from the Arguments collection.
    var objArgs = WScript.Arguments; // Create object.
    if (objArgs.length > 0)          // Argument found.
        file = objArgs(0);           // Set filename to first argument.
    var Text = "Content of " + file + "\n\n";

    // Create FileSystemObject object to access the file system.
    var fso = WScript.CreateObject("Scripting.FileSystemObject");

    // Check whether file exists.
    if (fso.FileExists(file))
    {
        var txtStream = fso.OpenTextFile(file);  // Open text file.
        while (!txtStream.atEndOfStream)
            Text = Text + txtStream.ReadLine() + "\n";
    }
    else
    {
        WScript.Echo(" File \'" + file + "\' not found");
        WScript.Quit(1);
    }

    var wsh = WScript.CreateObject("WScript.Shell");
    if (wsh.Popup("Show results in dialog box?",0,Title,
                  vbYesNo + vbQuestion) == vbYes)
    {
        WScript.Echo(Text);
    }
    else
    {
        Text = MakeHTMLCode(Text, 0); // Convert text to HTML
        ShowWindow(Text, Title);      // (only < and >) in browser window.
    }

    // Helper functions
    function ShowWindow(txt, title)
    {
        // Create Internet Explorer Application object.
        var oIE = WScript.CreateObject("InternetExplorer.Application");
        oIE.navigate("about:blank"); // Empty HTML document
        oIE.visible = 1;             // Internet Explorer is visible.
        oIE.toolbar = 0;
        oIE.statusbar = 0;
        oIE.width=400;
        oIE.height=500;
        while (oIE.Busy) {}          // Important: Wait until Internet
                                     // Explorer is ready.

        var doc1 = oIE.Document;     // Get Document object.
        doc1.open;                   // Open document.
        // Write script to the document object.
        doc1.writeln("<html><head><title>");
        doc1.writeln(Title);
        doc1.writeln("</title></head>");
        doc1.writeln("<body bgcolor=\'#FAF0F0\'><pre>");
        doc1.writeln(txt);         // Text output
        doc1.writeln("</pre></body></html>");
        doc1.close;                 // Close document for write access.
    }

    function MakeHTMLCode(txt, flag)
    {
        // Convert text file to HTML structure.
        // Flag controls which elements are converted.
        // Use the following values:
        // 0: Convert all < and > characters to &lt; and &gt;.
        // 1: Like flag = 0, but also sets \n to <br> tag
        //    (forces line wrap).
        // 2: Like flag = 2, but also sets blanks to &nbsp;.
        // ### Be careful of the order of pattern replacement. ###

     // Replace all < with &lt;. (Use regular expression.)
        txt = txt.replace(/</ig, "&lt;");

        // Replace all > with &gt;.
        txt = txt.replace(/>/ig, "&gt;");

        if (flag > 0)                // Replace \n?
            txt = txt.replace(/\n/ig, "<br>");

        if (flag > 1)               // Replace blanks?
            txt = txt.replace(/ /ig, "&nbsp;");
        return txt;
    }

    //*** End

## Writing to a Text File

The following short sample opens the Autoexec.bat file, copies the content to a new file, and appends the line Set Born=Hello to the new file. This line causes Windows 95 or Windows 98 to create the environment variable Born at the next system startup.

> NOTE

> In Windows NT and Windows 2000, you can simply create a test file named C:\Autoexec.bat and add a few text lines to enable the script to run.

To access the text file, you need the FileSystemObject object. The file must be opened using the OpenTextFile method. As mentioned earlier, you can use the parameters passed to the method to control the access mode. The following statement opens the text file for write access. (The named constant ForWriting must be set to 2.)

    Set txtStreamOut = fso.OpenTextFile(file2, ForWriting, True)

If a value of True is passed in the third parameter, the text file is created if it doesn't exist.

> NOTE

> VBScript doesn't recognize the constant ForWriting, so you must either declare it in the script (if you use .vbs or .js files) or use a .wsf file and define a reference to the type library (as shown in several previous samples).

During the write process (using ForWriting mode), the output file is filled line by line, starting from the beginning of the file. The following sequence copies the content of the text file txtStream to txtStreamOut. Then a new line is appended to the output file.

    Do While Not (txtStream.atEndOfStream)   ' Copy file content.
        Text = txtStream.ReadLine            ' Read line.
        txtStreamOut.WriteLine Text          ' Write line.
    Loop

    ' Append a new line.
    txtStreamOut.WriteLine "Set Born=Hello"

The WriteLine method inserts the new line of code automatically during each write access.

The script in Listing 12-19 reads the Autoexec.bat file, creates the output file Autoexec.xx1, copies the content of Autoexec.bat to the output file, and appends the new statement to the output file. After processing, a message box indicates that the file was created (Figure 12-15). If you execute the script several times, the same output file is always created because the write process rewrites the file each time.

Figure 12-15 Dialog box that appears after the Autoexec.bat file is copied

Listing 12-19 WriteTxt.vbs

    '**************************************************
    ' File:    WriteTxt.vbs (WSH sample in VBScript)
    ' Author:  (c) G. Born
    '
    ' Copying the content of a text file and appending
    ' a new line
    '**************************************************
    Option Explicit

    Const file1 = "C:\Autoexec.bat"   ' Our test file
    Const file2 = "C:\Autoexec.xx1"   ' The output file

    ' We must define ForWriting because the
    ' iomode constants are unknown to VBScript.
    Const ForWriting = 2              ' iomode: write access

    Dim Text
    Dim fso                           ' Object variable
    Dim txtStream, txtStreamOut       ' TextStream objects

    ' Create a FileSystemObject object to access the file system.
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' Check whether the file exists.
    If fso.FileExists(file1) Then
        Set txtStream = fso.OpenTextFile(file1) ' Open input file.
        Set txtStreamOut = fso.OpenTextFile(file2, _
                    ForWriting, True)           ' Open output file.

        Do While Not (txtStream.atEndOfStream)  ' Copy folder content.
            Text = txtStream.ReadLine           ' Read line.
            txtStreamOut.WriteLine Text         ' Write line.
        Loop

        txtStreamOut.WriteLine "Set Born=Hello" ' Append a line.

        Set txtStream = Nothing                 ' Release objects.
        Set txtStreamOut = Nothing

        WScript.Echo "Text file " & file1 & _
                     " copied and extended in " & file2
    Else
        WScript.Echo "File " & file & " not found."
    End If

    '*** End

### The JScript implementation

The JScript version (Listing 12-20) has the same structure as the VBScript program. The script creates the output text file Autoexec.xx1 using the Autoexec.bat content and then appends a new line (Figure 12-16).

Figure 12-16 Autoexec.xx1 shown in Notepad

Listing 12-20 WriteTxt.js

    //**************************************************
    // File:    WriteTxt.js (WSH sample in JScript)
    // Author:  (c) G. Born
    //
    // Copying the content of a text file and appending
    // a new line
    //**************************************************

    var file1 = "C:\\Autoexec.bat";     // Input file
    var file2 = "C:\\Autoexec.xx1";     // Output file
    var ForWriting = 2;                 // iomode: write access
    var Text;

    // Create a FileSystemObject object to access the file system.
    var fso = WScript.CreateObject("Scripting.FileSystemObject");

    if (fso.FileExists(file1))          // Check whether the file exists.
    {
        var txtStream = fso.OpenTextFile(file1);  // Open input file.
        var txtStreamOut = fso.OpenTextFile(file2,
                    ForWriting, true);            // Open output file.

        while (!txtStream.atEndOfStream)          // Copy folder content.
        {
            Text = txtStream.ReadLine();          // Read line.
            txtStreamOut.WriteLine(Text);         // Write line.
        }

        txtStreamOut.WriteLine("Set Born=Hello"); // Append line.

        WScript.Echo("Text file " + file1 +
                     " copied and extended in " + file2);
    }
    else
        WScript.Echo("File " + file + " not found.");

    //*** End

## Appending New Text to an Existing File

You might want to append some information to a text file when you process log files and in other situations. You can append new text to an existing text file by using the WriteLine method of the FileSystemObject object. Unlike in the preceding sample, you must set the second parameter to append mode. The following statement causes all data written to the text file to be appended. (The named constant ForAppend must be set to 8 if you use a .vbs or .js file, or else you need to use a .wsf file and define a reference to the type library, as shown in the following sample.)

    Set txtStream = fso.OpenTextFile(file2, ForAppend, True)

The value True in the third parameter forces the method to create a new file if the output text file is missing.

Listing 12-21 opens the C:\Autoexec.xx1 file and appends the text line Set Born=Hello. (The file C:\Autoexec.xx1 is created by the script called WriteTxt.vbs, shown in Listing 12-19.) If you execute the sample several times, the new line is appended each time to the existing file.

Listing 12-21 WriteTxt1.wsf

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!--
        File:    WriteTxt1.wsf (WSH 2)
        Author:  (c) G. Born
        Appending a line to a text file by using a reference
        to the FileSystemObject type library
    -->

    <job id="WriteTxt1">
        <reference guid='{420B2830-E718-11CF-893D-00A0C9054228}'/>

        <script language="VBScript">
        <![CDATA[
            Option Explicit

            Const file1 = "C:\Autoexec.xx1"

            '*** Const ForAppending = 8  ' Obtained from type library

            Dim Text
            Dim fso                 ' Object variable
            Dim txtStream           ' Text stream

            ' Create a FileSystemObject object to access the file system.
            Set fso = CreateObject("Scripting.FileSystemObject")

            If fso.FileExists(file1) Then  ' Check whether the file exists.
                Set txtStream = _
                    fso.OpenTextFile(file1, ForAppending)    ' Output file

                txtStream.WriteLine "Set Born=Hello" ' Append line.

                Set txtStream = Nothing    ' Release object.
                WScript.Echo "Text file " & file1 & " extended."
            Else
                WScript.Echo "File " & file1 & " not found."
            End If

            '*** End
        ]]>
        </script>
    </job>

### The JScript implementation

The JScript version is shown in Listing 12-22. This solution uses a simple .js file, so the constant ForAppending must be set to 8 within the script. However, you can easily use the code from Listing 12-21 and exchange the VBScript part with the code in this JScript listing and import the named constant ForAppending from the FileSystemObject type library.

Listing 12-22 WriteTxt1.js

    //************************************************
    // File:    WriteTxt1.js (WSH sample in JScript)
    // Author:  (c) G. Born
    //
    //  Appending a line to a text file
    //************************************************

    var file1 = "C:\\Autoexec.xx1";
    var ForAppending = 8;               // Writing
    var Text = "Set Born=Hello";

    // Create a FileSystemObject object to access the file system.
    var fso = WScript.CreateObject("Scripting.FileSystemObject");

    if (fso.FileExists(file1))   // Check whether the file exists.
    {
        var txtStream = fso.OpenTextFile(file1,
                    ForAppending, true); // Output file

        txtStream.WriteLine(Text);       // Append line.

        WScript.Echo("Text file " + file1 + " extended.");
    }
    else
        WScript.Echo("File " + file + " not found.");

    //*** End

## Replacing Text in a File

The next sample combines some of the knowledge you gained in the previous sections to read data from an input file, search for patterns, replace all matches with a string, and write the result to another file. The sample reads the TestFile.txt file (which must be in the same folder as the script file) and then changes all occurrences of the ' character to //#. The result is written to a second file, TestFile1.txt.

All you need to do is combine code snippets from previous examples. To get the path to the script file, you can use the following line:

    path = GetPath

The GetPath function contains the following statements:

    Function GetPath
        ' Retrieve the script path.
        Dim path
        path = WScript.ScriptFullName  ' Script name
        GetPath = Left(path, InStrRev(path, "\"))
    End Function

After retrieving the path, you can open the input file and create the output file by using the following sequence:

    Set fso = CreateObject("Scripting.FileSystemObject")
    If Not fso.FileExists(fileIn) Then WScript.Quit 1
    Set oFileIn = fso.OpenTextFile(path & "TestFile.txt")
    Set oFileOut = fso.OpenTextFile(path & "TestFile1.txt", _
                                    ForWriting, True)

The first line creates an instance of the FileSystemObject object. The second line checks whether the input file exists. If it does, it's opened using the OpenTextFile method in the third line. Because you need only read access to the file, just the filename is passed as a parameter. The last statement opens the output file. The second parameter submitted to the OpenTextFile method is set to ForWriting so that you can write to the file.

You process the input file and replace all matches with the replacement text by using the following code sequence:

    Do While Not (oFileIn.atEndOfStream)
        Text = oFileIn.ReadLine               ' Read a line.
        Text = Filter(Text, pattern, replacement)
        oFileOut.WriteLine Text               ' Write text.
    Loop

The Do While loop terminates if the atEndOfStream method of the input file returns the value True. If the file is empty, atEndOfStream returns True immediately and the loop is skipped; otherwise, atEndOfStream returns True only after ReadLine reads the last line in the file. The second statement within the loop calls the user-defined function Filter, which has three parameters: the first parameter contains the string to be processed, the second parameter specifies the search pattern, and the third parameter specifies the replacement string. The sample specifies the parameters pattern and replacement as constants. The last line within the loop simply writes the text returned from the Filter function to the output file.

The Filter function contains the code that does the replacement. We used a similar approach earlier in the chapter in the ReadTxt.vbs sample, so I reused most of the code for this sample.

    Function Filter(txt, expr1, expr2)
        ' Replaces expr1 with expr2 in text.
        Dim oReg

        Set oReg = New RegExp        ' Create regular expression.
        oReg.Global = True           ' All matches
        oReg.IgnoreCase = True       ' Make case insensitive.

        ' Replace all expr1 with expr2
        oReg.Pattern = expr1         ' Set pattern.
        Filter = oReg.Replace(txt, expr2)
    End Function

The function creates a regular expression object oReg. Then the properties of this object are set to force a global operation. The Replace method ensures that all occurrences of the parameter expr1 are replaced by the string contained in expr2.

Listing 12-23 shows the full VBScript program.

Listing 12-23 ReplaceTxt.vbs

    '**************************************************
    ' File:    ReplaceTxt.vbs (WSH sample in VBScript)
    ' Author:  (c) G. Born
    '
    ' Reading a file, replacing a given pattern in the
    ' file, and writing the result to another file
    '**************************************************
    Option Explicit

    ' We must define ForWriting because the
    ' iomode constants are unknown to VBScript.
    Const ForWriting = 2              ' iomode: write access

    Const inF = "TestFile.txt"
    Const outF = "TestFile1.txt"

    ' Here are the strings for replacement.
    Const pattern = "'"
    Const replacement = "//#"

    Dim Text
    Dim fso                 ' Object variable
    Dim oFileIn, oFileOut   ' Text stream
    Dim path, fileIn, fileOut

    path = GetPath()        ' Retrieve current path to script.
    fileIn = path & inF     ' Create filenames.
    fileOut = path & outF

    ' Create a FileSystemObject object to access the file system.
    Set fso = CreateObject("Scripting.FileSystemObject")

    If Not fso.FileExists(fileIn) Then  ' Input file exists?
        WScript.Echo "File '" & fileIn & "' not found"
        WScript.Quit 1
    End If

    ' Input file present; open file and create output file.
    Set oFileIn = fso.OpenTextFile(fileIn)   ' Open input file.
    Set oFileOut = fso.OpenTextFile(fileOut, _
                        ForWriting, True)    ' Open output file.

    Do While Not (oFileIn.atEndOfStream)
        Text = oFileIn.ReadLine              ' Read a line.
        Text = Filter(Text, pattern, replacement)
        oFileOut.WriteLine Text              ' Write text.
    Loop

    WScript.Echo "Text file: " & fileIn & vbCrLf & _
                 "Written into: " & fileOut

    Function GetPath
        ' Retrieve the script path.
        Dim path
        path = WScript.ScriptFullName  ' Script name
        GetPath = Left(path, InStrRev(path, "\"))
    End Function

    Function Filter(txt, expr1, expr2)
        ' Replace expr1 with expr2 in text.
        Dim oReg

        Set oReg = New RegExp        ' Create regular expression.
        oReg.Global = True           ' All matches
        oReg.IgnoreCase = True       ' Make case-insensitive.

        ' Replace all expr1 with expr2.
        oReg.Pattern = expr1          ' Set pattern.
        Filter = oReg.Replace(txt, expr2)
    End Function

    '*** End

> NOTE

> You can extend ReplaceTxt.vbs in a number of ways. For example, you can extend it so that it accepts a matching pattern, a replacement pattern, and one or several filenames. Then you can apply the program to a group of files to replace a given string with a second string.