Input and Output

Opening Files or Pipes

In order to read from a file (or pipe), or to write to it, you'll need to open it first. The general stanza is:

 # Open a file to read
 open(my $in, "/where/ever.txt") or die("Cannot read /where/ever.txt: $!\n");

The magic sequence $! is a string that describes the error, such as "no such file or directory", or "permission denied", etc..

The first or last part of the file name can be a modifier that specifies how the file should be opened (when not for reading). Examples:

 # Rewrite a file
 open(my $of, ">/where/ever.txt") or die(...);

 # Append to a file
 open(my $of, ">>/where/ever.txt") or die(...);

 # Read from a pipe
 open(my $if, "ls /where/ever |") or die(...);

 # Write a pipe
 open(my $of, '|mail -s "Test Subject" user@example.com') or die(...);

Reading from Files or Pipes

Line-oriented input is best read using < and > around the file handle. The line will usually be \n-terminated, unless of course you're reading a file where the last line doesn't have a newline terminator.

 while (my $line = <$if>) {
    print("Got line: $line");
 }

Note that there are also direct methods that don't mind lines, such as sysread(), which read large chunks at a time.

Writing to Files or Pipes

Writing is usually done using print:

 print $of ("Here is my information\n");

Exercise

Write a program that is invoked as "logwarn file(s)". The file(s) are typically log files under /var/log. The program scans the files and lines that have the word "warning" in them, are shown on screen. This is a simple utility to see what's going on in the system. A sample invocation might be: "logwarn /var/log/system.log" (on MacOSX).

Here's the catch: the files may also be gzipped files, as in "logwarn /var/log/system.log.0.gz". In this case logwarn shouldn't just open the plain file, but a pipe "gunzip -c /var/log/system.log.0.gz" and read from that pipe.

After opening (whether it's a plain file or a pipe), the program can just read lines and display them if necessary.

Exercise

Here's a tough one.

 Groningen,Leeuwarden,64
 Leeuwarden,Den Helder,91
 Den Helder,Amsterdam,99
 Amsterdam,Rotterdam,79
 Amsterdam,Utrecht,41
 Rotterdam,Utrecht,57
 Rotterdam,Den Bosch,84
 Den Bosch,Utrecht,59
 Den Bosch,Breda,48
 Den Bosch,Eindhoven,37
 Eindhoven,Venlo,57
 Eindhoven,Maastricht,88
 Venlo,Maastricht,76
 Venlo,Nijmegen,62
 Eindhoven,Nijmegen,65
 Den Bosch,Nijmegen,48
 Nijmegen,Arnhem,24
 Arnhem,Utrecht,65
 Arnhem,Zwolle,52
 Assen,Zwolle,75
 Leeuwarden,Zwolle,92
 Assen,Groningen,32