Приглашаем посетить
Чуковский (chukovskiy.lit-info.ru)

15.2 Using server storage

Table of Contents

Previous Next

15.2 Using server storage

15.2.1 Open a file for reading

Using server storage creates a permanent and reliable record for your Web activity, which in many cases is vital for many applications. For a simple page counter, database, or money transaction business, the ability to use server storage is critical.

To open a file using Perl script, the following statement is often used:



open (filehandle, "<filename");

This open command opens the file filename for reading and assigns a filehandle variable to control it. For different file operations, there are different file open modes. Some of the frequently used file open modes are listed in Table 15.1.

Table 15.1. File open modes

Mode

Operation

Description and example

<

Reading

Open a file for reading, e.g., open (filehandle, "<filename");

>

Writing

Create a file for writing. If the file already exists, discard the contents, e.g., open (filehandle, ">filename");

>>

Append

Open or create a file for writing. If the file exists, writing is at the end of the file, e.g., open (filehandle, ">>filename");

+>

Update

Create a file for update. If the file exists, discard the contents, e.g., open (filehandle, "+>filename");

+<

Reading & writing

Open the file for update (i.e., reading and writing). Keep the contents of the file, e.g., open (filehandle, "+<filename");

+>>

Update & append

Open or create a file for update. Writing is at the end of the file, e.g., open (filehandle, "+>>filename");


From the examples in this table, the file open mode is applied at the front of the file name. When there is no open mode specified, the reading mode is assumed as the default.

To open and display the contents of a file, the following Perl script is used:



Example: ex15-03.pl - Open A File For Reading

 1: #!/usr/bin/perl
 2: open(filehandle,"message.dat")
 3:   or die("Cannot open message.dat for reading");
 4:
 5: while (my $st = <filehandle>)
 6: {
 7:   print("$st");
 8: }
 9: close(filehandle);
10:

This Perl script opens a file called message.dat for reading. If not successful, the die statement displays a message and terminates the program. If the file operation is successful, a while-loop is used in lines 58 to display the contents of the file. The statement



$st = <filehandle>

reads a string from the file until a new line is encountered. The string is then assigned to the variable $st. The print statement in line 7 is a typical statement to display the string to the standard out. It is important to close any opened file at the end of the program, as illustrated in line 9.

This program is a standard application of Perl and will work on any system with a Perl interpreter. If you issue the command



perl ex15-03.pl

the result will be displayed on the console window. To convert the program to a CGI application, you may need to add the string "Content-type: text/html\n\n" to the program and construct the returned message as an XHTML document. Consider the following modification:



Example: ex15-04.pl - Open A File For Reading (CGI)

 1: #!/usr/bin/perl
 2: print ("Content-type:text/html\n\n");
 3:
 4: print << "mypage";
 5:  <?xml version="1.0" encoding="iso-8859-1"?>
 6:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 7:  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 8:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 9:  <head><title>Example: ex15-04.pl</title></head>
10:  <style>.txtSt{font-size:18pt;color:#ffff00;font-family:arial}</style>
11:  <body style="background:#000088" class="txtSt">
12: mypage
13:
14: open(filehandle,"message.dat")
15:   or die("Cannot open message.dat for reading");
16:
17: while (my $st = <filehandle>)
18: {
19:   print("$st <br />");
20: }
21: close(filehandle);
22:
23: print " </body></html>";

After the XHTML header message in lines 412, the only real modification of this program is that the string $st is printed with a line break element <br /> so that a line break is generated (see Fig. 15.4).

Figure 15.4. ex15-04.p1

graphics/15fig04.jpg


To convert this example into a practical application, let's consider a page to read old company memos or articles.

15.2.2 A page to trace old records

Sometimes, back tracking for information such as company memos, newsletters, product support, important emails, and frequently asked questions (faq) could be an administrative nightmare for a company. A server to store all these old records and be available via a Web page could be quite handy. The next example is a simple file-based Web page to trace back records. First, we collect all faq monthly and store them in the text files on the server. The next step is to develop a page to display them.

The implementation is divided into two parts. The first part is a simple XHTML document with a select box to allow the user to pick the item he or she would like to read. The second part is a Perl script to handle the file and display it on a separate browser window.

The interface part of this example is listed below:



Example: ex15-05.htm - A Page To Trace Old Records

 1: <?xml version="1.0" encoding="iso-8859-1"?>
 2: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 3:     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 5: <style> .selSt{width:380px;height:35px;background:#aaffaa;
 6: font-family:arial;font-weight:bold;font-size:16pt;color:#880000}</style>
 7: <head><title>Monthly FAQ  ex15-05.htm</title></head>
 8: <body style="background:#000088;font-family:arial;font-size:22pt;
 9:      color:#ffff00;font-weight:bold;text-align:center"><br />
10:  Monthly FAQ Available For <br />Company Staff To Read<br />
11:
12: <form action="ex15-05.pl" method="post" target="_blank">
13:  <div style="position:absolute;top:150px;left:60px;text-align:left;
14:         font-size:18pt">Monthly FAQ Available<br />
15:   <select id="monthly" name="monthlyFAQ" class="selSt">
16:    <option>November</option>
17:    <option>October</option>
18:    <option>September</option>
19:    <option>August</option>
20:  </select><br /><br /><br />
21: </div>
22: <input type="submit" value="Read"
23:    style="position:absolute;top:155px;left:460px;width:100px;
24:    height:60px;font-family:arial;font-size:18pt;font-weight:bold" />
25: </form>
26: </body></html>

This is a simple XHTML page containing a select box (lines 1519) with the four selections "November," "October," "September," and "August." When one of the selections is picked and the Read button is pressed, the form action defined in line 12 activates the Perl script ex15-05.pl. Since we have used the attribute target=_blank, the result will be displayed in another separate browser window. The function of the Perl script ex15-05.pl is to get the selection and display the corresponding file on the screen. Some screen shots of this example are shown in Figs 15.5 and 15.6.

Figure 15.5. ex15-05.htm

graphics/15fig05.jpg


Figure 15.6. ex15-05.p1

graphics/15fig06.jpg


The form action in line 12 assumes that the Web page, Perl script, and old documents are stored on the same server. If the script and document are stored on another site such as www.pwt-ex.com, you may need to use:



<form action="http://www.pwt-ex.com/ex15-05.pl" method="post"
target="_blank">

The Perl program used in this example is listed below:



Example: ex15-05.p1 - The Perl Script For ex15-05.htm

 1: #!/usr/bin/perl
 2: use CGI qw( :standard);
 3: print ("Content-type:text/html\n\n");
 4:
 5: my $fileN = param("monthlyFAQ");
 6:
 7: print << "mypage";
 8:  <?xml version="1.0" encoding="iso-8859-1"?>
 9:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
10:  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
11:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12:  <head><title>Example: ex15-05.pl</title></head>
13:  <style>.txtSt{font-size:18pt;color:#ffff00;font-family:arial}</style>
14:  <body style="background:#000088" class="txtSt">
15: mypage
16:
17: $fileN = $fileN . "\.txt";
18: open(filehandle,"<$fileN")
19:   or die("Cannot open file for reading");
20:
21: while (my $st = <filehandle>)
22: {
23:   print("$st<br />");
24: }
25: close(filehandle);
26:
27: print " </body></html>";
28:

In this script, we have used a Perl CGI module in line 2 so that parameters from the XHTML document can be accessed by using the param() function. The picked value is stored in the variable $fileN in line 5 and then used in line 17 to compose the file name by adding a file extension. The remainder of the program is to open the file and display the contents to a newly opened browser window.

This example is particularly useful for tracing text-based files. Since no XHTML statement is involved, it is economical to maintain.

15.2.3 Open a file for reading and writing

To open a file for writing, the following basic Perl script can be used:



Listing ex15-03.txt - Open A File For Writing

1: #!user/bin/perl
2: print ("Content-type:text/html\n\n");
3: open (outfile, ">file.txt")
4:    or die("Cannot Open File.. Error");
5: print (outfile "I know how to create a file using Perl script\n");
6: close(outfile);

Line 3 is a typical open statement to open a file for writing. If the file already exists, the contents will be destroyed. If the file is successfully opened, the open command returns a file handle. In this case, the file handle is called outfile. Using this file handle, you can employ a print command such as



print (outfile "Write something into the file");

to write something into the file.

However, in order to write something into a file and read it back, you need to open the file twice. In this case, it is a combination of both examples ex15-04.pl and ex15-05.pl. Consider the following Perl script:



Example: ex15-06.pl - Open A File For Reading And Writing

 1: #!user/bin/perl
 2: print ("Content-type:text/html\n\n");
 3: open (outfile,">file.txt")
 4:    or die("Cannot Open File For Writing.. Error");
 5: print (outfile "I know how to create a file using Perl script\n");
 6: close(outfile);
 7:
 8: open (infile, "<file.txt")
 9:    or die("Cannot Open File For Reading.. Error");
10: while (my $st = <infile>)
11: {
12:   print("$st");
13: }
14: close(infile);

This Perl script contains two processes. The first one is to open a file called file.txt and write something into it. Soon after the writing, the file is closed by executing the statement in line 6. The file is opened again by another handle called infile. Using this handle, the contents of the file are read and displayed. One immediate application of file reading and writing is to build a page counter for your site.

15.2.4 Building a Web page counter

Counters are frequently used on the World Wide Web to show how many people have visited your site. Normally, a counter is implemented as an ordinary text file to store a single value representing the number of accesses to a document. Once the page is requested, the counter file is opened, increments the value by 1, and then stores the value back to the file.

You can place different counter files for different articles, documents, or even topics. A number of ISPs also provide this feature with graphical displays; we will cover this in a moment. First, let's consider a basic implementation of a page counter on the Internet.



Example: ex15-07.pl - A Page Counter With Perl

 1: #!usr/bin/perl
 2: open(filehandle,"+<counter.txt")
 3:   or die("Cannot Open File  counter.txt .. Error");
 4: $countNumber = <filehandle>;
 5: $countNumber++;
 6: seek(filehandle,0,0);  ## rewind the file to the beginning
 7: print (filehandle "$countNumber");
 8: close(filehandle);

This Perl script has only eight lines of code. Suppose you have already created a counter file called counter.txt using an editor with a number on it. The open statement in line 2 opens the file for reading and writing. If the file operation is successful, you will have a filehandle to control the file. Line 4 is a read statement from Perl script to read the value from the file and store it in the variable $counterNumber. After adding 1 to this variable, you may need to rewind the file to the beginning before you can actually write the new value into the file. The new command seek(filehandle,0,0) in Perl script is used to demonstrate how to rewind a file to the beginning. Alternatively, you can close the file and then reopen it for writing.

To apply this Perl script to a CGI application, the following page with graphical images is used:



Example: ex15-08.pl - A Page Counter With Graphical Display

 1: #!usr/bin/perl
 2: print "Content-type:text/html\n\n";
 3: open(filehandle,"+<counter.txt")
 4:   or die("Cannot Open File  counter.txt .. Error");
 5: $countNumber = <filehandle>;
 6: $countNumber++;
 7: seek(filehandle,0,0);
 8: print (filehandle "$countNumber");
 9: close(filehandle);
10:
11: print << "mypage";
12:  <?xml version="1.0" encoding="iso-8859-1"?>
13:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
14:  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
15:  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
16:  <head><title>Example: ex15-08.pl</title></head>
17:  <style>.txtSt{font-size:18pt;color:#ffff00;font-family:arial}</style>
18:  <body style="background:#000088" class="txtSt">
19: mypage
20:
21: print" <div style=\"text-align:center\">You are visitor number : ";
22: for($ii=0; $ii < length($countNumber);$ii++)
23: {
24:   $jj = substr($countNumber,$ii,1);
25:   $pic = $jj . "dc.gif";
26:   print "<img src=\"$pic\" alt=\"pic\" \/>";
27: }
28: print "</div><br /><br />";
29:
30: print "Your XHTML document can be here..<br /><br />";
31:
32: print "</body></html>";

Lines 39 are the counter implementation similar to ex15-07.pl. After the variable $countNumber and file are updated, lines 1119 generate the header for an XHTML document. The interesting part of this script is the code in lines 2227. This is a for-loop in Perl script to convert the number of visits to graphical display. Basically, it is used to extract the digits of the $countNumber one by one. When $ii equals 0, the command



$jj = substr($countNumber,0,1)

extracts the first character of $countNumber to variable $jj. The value of $jj is then used to compose the digit picture. For example, if $jj = 3, the value of $pic would be a string 3dc.gif and the print statement would output the XHTML image element



<img src="3dc.gif" />

to the browser. The picture 3dc.gif is a graphical image of 3 (see section 12.3.2). A screen shot of this example in action is shown in Fig. 15.7.

Figure 15.7. ex15-08.p1

graphics/15fig07.jpg


When the page operates on the Internet, many users can access the Web page at the same time. This might create a danger when more than one user tries to open and alter a file at the same time. We need something to protect against file corruption or inaccuracy when handling multiple accesses.

15.2.5 Sharing files among multiple Web users

When multiple users try to access the same file, it is possible that two of them might read the current count and increment it by 1 at the same time. As a result only one new value is stored back to the file. For an example like this, the chances of experiencing difficulties due to concurrent access may not be very high since the frequency of document access is small. However, consider a seat allocation system for an airline counter in a busy airport. The concurrent access situations may be a major operational problem to be solved.

Perl does include facilities for synchronizing file accesses. A typical solution is to use the flock() function, which allows users to lock a file for private use. For example, you can use the statement:



flock(filehandle,2);

to lock the file immediately through the file handle. All other access to the file is denied. That is, if a script is writing, no other scripts or executable programs will be given access until that script is finished. Some Perl installations may use the command flock(filehandle,LOCK_EX); where the numeric value 2 is replaced by an identifier defined in some Perl modules.

To prevent the problem of inconvenient locking of the file for a long period of time, you should unlock the file soon after your file operation. The command to unlock a file is



flock(filehandle,8);

or flock(filehandle, LOCK_UN); for some Perl installations and additional modules.

You now have some ideas on server storage and how to use them. It is time to consider some basic CGI applications on the Web.

    Table of Contents

    Previous Next