⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch21.htm

📁 prrl 5 programs codes in the book
💻 HTM
📖 第 1 页 / 共 5 页
字号:

</CENTER>

<P>

<P>

<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>

<BLOCKQUOTE>

<I>Turn on the warning option.<BR>

Turn on the strict pragma.<BR>

Declare some variables.<BR>

Call the </I><TT><I>checkFiles()</I></TT><I>

fuNCtion to find modified files.<BR>

Call the </I><TT><I>setLastTime()</I></TT><I>

fuNCtion to update the log file.<BR>

Call the </I><TT><I>createHTML()</I></TT><I>

fuNCtion to create the web page.<BR>

<BR>

Define the </I><TT><I>getLastTime()</I></TT><I>

fuNCtion.<BR>

Declare local variables to hold the parameters.<BR>

If the data file can't be opened, use the current time as the

default.<BR>

Read in the time of the last running of the program.<BR>

Close the data file.<BR>

Return the time.<BR>

Define the </I><TT><I>setLastTime()</I></TT><I>

fuNCtion.<BR>

Declare local variables to hold the parameters.<BR>

Open the data file for writing.<BR>

Output </I><TT><I>$time</I></TT><I>

which is the current time this program is running.  <BR>

Close the data file.<BR>

Define the </I><TT><I>checkFiles()</I></TT><I>

fuNCtion.<BR>

Declare local variables to hold the parameters.<BR>

Declare more local variables.<BR>

Create an array containing the files in the </I><TT><I>$path</I></TT><I>

directory.<BR>

Iterate over the list of files.<BR>

If current file is current dir or parent dir, move on to next

file.<BR>

Create full filename by joining dir (</I><TT><I>$path</I></TT><I>)

with filename (</I><TT><I>$_</I></TT><I>).

<BR>

If current file is a directory, then recurse and move to next

file.<BR>

Get last modification time of current file.<BR>

Provide a default value for the file's title.<BR>

If the file has been changed siNCe the last running of this program,open

the file, look for a title HTML tag, and close the file.<BR>

Create an anonymous array and assign it to a hash entry.<BR>

Define the </I><TT><I>createHTML()</I></TT><I>

fuNCtion.<BR>

Declare local variables to hold the parameters.<BR>

Declare more local variables.<BR>

Open the HTML file for output.<BR>

Output the HTML header and title tags.<BR>

Output an H1 header tag.<BR>

If no files have changed, output a message.<BR>

Otherwise output the HTML tags to begin a table.<BR>

Iterate the list of modified files.<BR>

Output info about modified file as an HTML table row.<BR>

Output the HTML tags to end a table.<BR>

Output the HTML tags to end the document.<BR>

Close the HTML file.</I>

</BLOCKQUOTE>

<HR>

<P>

<B>Listing 21.7&nbsp;&nbsp;21LST07.PL-Generating a Primitive What's

New Page<BR>

</B>

<BLOCKQUOTE>

<PRE>#!/usr/bin/perl -w

use strict;



my($root)     = &quot;/website/root&quot;;          # root of server

my($newLog)   = &quot;new.log&quot;;                # file w/time of last run.

my($htmlFile) = &quot;$root/whatnew.htm&quot;;      # output file.

my($lastTime) = getLastTime($newLog);     # time of last run.

my(%modList);                             # hash of modified files.



checkFiles($root, $root, $lastTime, \%modList);

setLastTime($newLog, time());

createHTML($htmlFile, $lastTime, \%modList);



sub getLastTime {

    my($newLog) = shift;        # filename of log file.

    my($time)   = time();       # the current time is the default.



    if (open(NEWLOG, &quot;&lt;$newLog&quot;)) {

        chomp($time = &lt;NEWLOG&gt;);

        close(NEWLOG);

    }

    return($time);

}



sub setLastTime {

    my($newLog) = shift;        # filename of log file.

    my($time)   = shift;        # the time of this run.



    open(NEWLOG, &quot;&gt;$newLog&quot;) or die(&quot;Can't write What's New log file.&quot;);

    print NEWLOG (&quot;$time\n&quot;);

    close(NEWLOG);

}



sub checkFiles {

    my($base)    = shift;   # the root of the dir tree to search

    my($path)    = shift;   # the current dir as we recurse

    my($time)    = shift;   # the time of the last run of this script

    my($hashRef) = shift;   # the hash where modified files are listed.

    my($fullFilename);      # a combo of $path and the current filename.

    my(@files);             # holds a list of files in current dir.

    my($title);             # the HTML title of a modified doc.

    my($modTime);           # the modification time of a modfied doc.



    opendir(ROOT, $path);

    @files = readdir(ROOT);

    closedir(ROOT);



    foreach (@files) {

        next if /^\.|\.\.$/;



        

        $fullFilename    = &quot;$path/$_&quot;;



        if (-d $fullFilename) {

            checkFiles($base, $fullFilename, $time, $hashRef);

            next;

        }



        $modTime = (stat($fullFilename))[9]; # only need the mod time.

        $title   = 'Untitled';               # provide a default value



        if ($modTime &gt; $time) {

            open(FILE, $fullFilename);

                while (&lt;FILE&gt;) {

                    if (m!&lt;title&gt;(.+)&lt;/title&gt;!i) {

                        $title = $1;

                        last;

                    }

                }

            close(FILE);



            %{$hashRef}-&gt;{substr($fullFilename, length($base))} =

                [ $modTime, $title ];

        }

    }

}





sub createHTML {

    my($htmlFile)   = shift;

    my($lastTime)   = shift;

    my($hashRef)    = shift;

    my($htmlTitle)  = &quot;What's New SiNCe &quot; . scalar(localtime($lastTime)). &quot;!&quot;;

    my(@sortedList) = sort(keys(%{$hashRef}));



    open(HTML, &quot;&gt;$htmlFile&quot;);



    print HTML (&quot;&lt;TITLE&gt;$htmlTitle&lt;/TITLE&gt;\n&quot;);

    print HTML (&quot;&lt;HTML&gt;\n&quot;);

    print HTML (&quot;&lt;HEAD&gt;&lt;TITLE&gt;$htmlTitle&lt;/TITLE&gt;&lt;/HEAD&gt;\n&quot;);

    print HTML (&quot;&lt;BODY&gt;\n&quot;);

    print HTML (&quot;&lt;H1&gt;$htmlTitle&lt;/H1&gt;&lt;P&gt;\n&quot;);



    if (scalar(@sortedList) == 0) {

        print HTML (&quot;There are no new files.\n&quot;);

    }

    else {

        print HTML (&quot;&lt;TABLE BORDER=1 CELLPADDING=10&gt;\n&quot;);

        print HTML (&quot;&lt;TR&gt;\n&quot;);

        print HTML (&quot;  &lt;TH&gt;Filename&lt;/TH&gt;\n&quot;);

        print HTML (&quot;  &lt;TH&gt;Modification&lt;BR&gt;Date&lt;/TH&gt;\n&quot;);

        print HTML (&quot;  &lt;TH&gt;Title&lt;/TH&gt;\n&quot;);

        print HTML (&quot;&lt;/TR&gt;\n&quot;);

        foreach (sort(keys(%{$hashRef}))) {

            my($modTime, $title) = @{%{$hashRef}-&gt;{$_}};



            $modTime = scalar(localtime($modTime));

            print HTML (&quot;&lt;TR&gt;\n&quot;);

            print HTML (&quot;  &lt;TD&gt;&lt;FONT SIZE=2&gt;&lt;A HREF=\&quot;$_\&quot;&gt;$_&lt;/A&gt;&lt;/FONT&gt;&lt;/TD&gt;\n&quot;);

            print HTML (&quot;  &lt;TD&gt;&lt;FONT SIZE=2&gt;$modTime&lt;/FONT&gt;&lt;/TD&gt;\n&quot;);

            print HTML (&quot;  &lt;TD&gt;&lt;FONT SIZE=2&gt;$title&lt;/FONT&gt;&lt;/TD&gt;\n&quot;);

            print HTML (&quot;&lt;/TR&gt;\n&quot;);

        }

        print HTML (&quot;&lt;/TABLE&gt;\n&quot;);

    }



    print HTML (&quot;&lt;/BODY&gt;\n&quot;);

    print HTML (&quot;&lt;/HTML&gt;\n&quot;);

    close(HTML);

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

The program from Listing 21.7 will generate an HTML file that

can be displayed in any browser capable of handling HTML tables.

Figure 21.2 shows how the page looks in Netscape Navigator.

<P>

<A HREF="f21-2.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/f21-2.gif"><B>Figure 21.2 : </B><I>A What's New page</I>.</A>

<P>

You might wonder why I end the HTML lines with newline characters

when newlines are ignored by Web browsers. The newline characters

will help you to edit the resulting HTML file with a standard

text editor if you need to make an emergeNCy change. For example,

a document might change status from <TT>visible</TT>

to <TT>for internal use only</TT>

and you'd like to remove it from the What's New page. It is much

easier to fire up a text editor and remove the refereNCe then

to rerun the What's New script.

<P>

I think the only tricky code in Listing 22.7 is where it creates

an anonymous array that is stored into the hash that holds the

changed files. Look at that line of code closely.

<BLOCKQUOTE>

<PRE>%{$hashRef}-&gt;{substr($fullFilename, length($base))} = [ $modTime, $title 

</PRE>

</BLOCKQUOTE>

<P>

The <TT>$hashRef</TT> variable holds

a refereNCe to <TT>%modList</TT> that

was passed from the main program. The key part of the key-value

pair for this hash is the relative path and file name. The value

part is an anonymous array that holds the modification time and

the document title.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Tip</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

An array was used to store the information about the modified file so that you can easily change the program to display additional information. You might also want to display the file size or perhaps some category information.</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

Using the relative path in the key becomes important when the

HTML file is created. In order to create hypertext links to the

changed documents, the links need to have the document's directory

relative to the server's root directory. For example, my WebSite

server has a base directory of <TT>/website/root</TT>.

If a document changes in <TT>/website/root/apache</TT>,

then the hypertext link must use <TT>/apache</TT>

as the relative path in order for the user's Web browser to find

the file. To arrive at the relative path, the program simply takes

the full path and filename and removes the beginning of the string

value using the <TT>substr()</TT>

fuNCtion.

<P>

You might also want to know a bit about the recursive nature of

the <TT>checkFiles()</TT> fuNCtion.

This book really hasn't mentioned recursive fuNCtions in any detail

yet. So, I'll take this opportunity to explain them.

<P>

A <I>recursive fuNCtion</I> calls itself in order to get work

done. One classic example of recursiveness is the <TT>factorial()</TT>

fuNCtion from the math world. 3! (five factorial) is the same

as 1*2*3 or 6. The <TT>factorial()</TT>

fuNCtion looks like this:

<BLOCKQUOTE>

<PRE>sub factorial {

    my($n) = shift;



    return(1) if $n == 1;

    return($n * factorial($n-1));

}

</PRE>

</BLOCKQUOTE>

<P>

Now track the value of the return statements when factorial(3)

is called:

<OL>

<LI><B>factorial(3)</B>-return(3 * factorial(2));

<LI><B>factorial(2)</B>-return(2 * factorial(1));

<LI><B>factorial(1)</B>-return(1);

<LI><B>factorial(2)</B>-return(2 * 1);

<LI><B>factorial(3)</B>-return(3 * 2);

<LI>A value of 6 is returned.

</OL>

<P>

First, the fuNCtion repeated calls itself (recurses) until an

end condition is reached. When the end condition is reached ($n

== 1) then the stack of fuNCtion calls is followed backwards to

read the final value of 6.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Caution</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

It is very important for a recursive fuNCtion to have an end condition. If not, the fuNCtion recurses until your system runs out of memory.</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

If you look back at the <TT>checkFiles()</TT>

fuNCtion, you see that the end condition is not explicitly stated.

When a directory has no subdirectories, the fuNCtion will stop

recursing. And instead of returning a value that is used in a

mathematical expression, a hash refereNCe is continually passed

where the information about changed files is stored.

<P>

While the topic is the information about the changed files, let

me mention the two directories that are used as parameters for

<TT>checkFiles()</TT>. The first directory

is the path to the Web server root-it will not change as the recursion

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -