in reply to Re: Reversing (the) reading of a file.
in thread Reversing (the) reading of a file.

The first thing I would do is decouple the code that gets the data from the code that displays the data. Splitting your code into getters and printers can make life a bit easier for you, especially if you need to display the same data in many different formats. I've tried to show an example of this below by allowing two different views of the data: a default view (in the format I think you were seeking) and a view of the articles by a single author.

Because each article is stored in a hash, it's easy to print the data however you want. Below, I used an array called @colOrder, that determines which values to display, and determines the order to display them.

I also used qq~ ~ instead of <<HTML. I find it much cleaner to use, partly because you don't have to worry about the indenting.

Also, if you're new to Perl, I'd suggest getting Learning Perl and The Camel, before picking up the Cookbook. IMO, learning how the language works will serve you better than seeking out ready-to-use code snippets. (they can be useful and save time if you know what the code does -- just don't use code until you understand how it works). If you're new to programming in general, I highly suggest Code Complete, which will help you write better organized and easier-to-read code -- a valuable skill no matter what language you use.

Okay, enough of my rambling, here's the code:

#!/usr/bin/perl -w use strict; ############ # INIT # ############ # Hardcoded params -- you'd probably get these from CGI, though my $view = ''; # In what format to view the data my $author = ''; # If viewing by author, which author? ############ # MAIN # ############ # These will be arrayrefs, so it's easier to pass them to subs my $articles = []; my $colOrder = []; # Print the article list, depending on the chosen view if ($view eq "byAuthor") { $colOrder = [qw.title date news.]; $articles = &get_articles_by_author($author); } else { # Default view $colOrder = [qw.title date author news.]; $articles = &get_articles(); } &print_articles($articles, $colOrder); ############ # SUBS # ############ ### Grabs all of the articles out of a data file and returns them as a +n ### array of hashrefs. This is the only sub you'll use to get the dat +a. If ### later you decide to put the articles in a db, you only have to cha +nge this ### one sub. sub get_articles { # Grab each line in reverse order open (NEWS, "<news.dat") or die "Can't open news file: $!"; my @articles = reverse <NEWS>; close(NEWS); # Your column names, in the order they appear in the file my @colNames = qw(time_stamp title date author news avatar); # Store the contents of the file in a table (array of hashrefs) my @table = (); foreach my $article (@articles) { chomp $article; my @vals = split /\|/, $article; # Assign each value to its column name, in a hash my %row = (); foreach my $col (@colNames) { $row{$col} = shift @vals; } # Add this row to the table, as a hashref push @table, \%row; } return \@table; } ### Get the list of articles by a single author, by getting the full +list of ### articles from the file, and then filtering out everything but the +given author. sub get_articles_by_author { my $author = shift || die "need an author"; my $articles = &get_articles(); # Build a list of articles by the given author my @artByAuth = (); foreach my $article (@$articles) { if ($article->{'author'} eq $author) { push @artByAuth, $article; } } return \@artByAuth; } ### Prints a given list of articles. ### Optional param: the order of columns to display. sub print_articles { my $articles = shift || die "Need an article list"; my $colOrder = shift || keys %{ $articles->[0] }; # Above, if no $colOrder was given, use all of the cols in the tab +le. # Just get the keys in the hash for the first article. # Print the articles print "Content-type:text/html\n\n"; print qq~<table width="400" border="1" cellspacing="0" cellpadding +="0">~; foreach my $article (@$articles) { foreach my $col (@$colOrder) { print qq~ <tr> <td>$article->{$col}</td> </tr> ~; } } print "</table><br>\n"; }


Of course, other monks will probably be able to suggest improvements that I've missed.

Have fun,   :)

joecamel