We know that the statement below reads a line from the Standard Input into the variable $input.
$input = <STDIN>;
What if we wanted to read input from another location, perhaps a file?
The simplest way is redirect STDIN from the command-line. This is a feature of the UNIX and DOS shell. It's not
dependent on Perl. To read a line from this file into your Perl script's $input variable, leave the Perl script
unchanged. When you run the script from the command line, follow it with a '<' symbol followed by the name of
the file. This is called redirecting.
Suppose you have a line of data in a file called: line_file.dat
In this case we use:
>perl MyPerlScript.pl < line_file.dat
When the Perl script executes this command:
$input = <STDIN>;
The first line of linefile.data is read into the $input variable as if you had typed it in on the keyboard,
including a new line character at the end.
The output which goes to STDOUT can also be redirected. On the command-line to execute Perl, follow the name of
the Perl script with a '>' symbol and the name of the file to write to. All of the output of your script that
would normally be displayed on the screen is instead sent to this file. If this file does not exist, it will be
created. If this file already exits, it will be overwritten.
Here's an example:
>perl MyPerlScript.pl > output_file.txt
I like to think of the '<' and '>' characters as arrow-heads. Input, '<', is sent into the perl script
you are executing and output, '>' comes out of your perl script into a file you designate.
You can comine redirection of input and output on the same line. For example:
>perl MyPerlScript.pl < line_file.dat > output_file.txt
This fetches input from line_file.dat and sends the resultant output to output_file.txt
You can change the way the output is redirect so that it doesn't overwrite a previous file with that name, but
instead appends to it by using '>>'.
This example appends to output_file.text if it exists, over wise, it creates it and then writes to it.
>perl MyPerlScript.pl > output_file.txt
Armed with this knowledge, you can now easily read the entire contents of a file into an array with one command.
@my_array = <STDIN>;
Whereas before, we read the contents of one line of STDIN into a scalar variable, here we assign STDIN to an array
variable. When operated on in the array (actually, list) context, all of the lines of STDIN are read into and end-of-file
(EOF) character is reached. The EOF character, naturally, comes at the end of every file.
So, after the command is executed, @my_array looks like this:
# From the file that has been directed to STDIN:
$my_array[0] # contains the contents of the first line of the file
$my_array[1] # contains the contents of the second line of the same file
: # and so on ...
$my_array[n] # contains the contents of the last line of the file
# where n = the number of lines in the file - 1.
You can access files in a more sophisticated way inside Perl by creating filehandles. A filehandle is a special
type of variable that points to a specific file. You initialize the filehandle with a file name and then use the
filehandle to read from or write data to the file.
You create and initialize a filehandle with the open command. It has this form:
open(FILEHANDLE, "<filename"); # opens a file for reading open(FILEHANDLE, ">filename"); # opens a file for writing
Note: The '<' and '>' characters here behave here as they did for redirecting STDIN and STDOUT
Examples:
open(INFILE, "<line_file.dat"); # opens this file for reading open(OUTFILE, ">out_file.txt"); # opens this file for writing
To send output to a file, use the print statement but include the filehandle as a parameter, like so:
print OUTFILE "I'm saving this line to the file";
This even works with STDOUT, which is the paramter assumed by default, anyway.
print STDOUT "I'm printing this line to STDOUT";
Note that a read operation requires that the file handle be enclosed in '<>', but the write operations do
not.
After you've finished reading or writing from a file in your perl script, it's a good idea to call the close()
function on the filehandle. This causes the writing of data to a file to finish before your script exits. (For
efficiency reaons, such data writing often occurs in the background while your script goes on to do other things.)
# This example copys all lines that are not blank from an input file to an output file
open(IN, "<line_file.dat"); # opens this file for reading
@file_contents = <IN>;
close(IN);
open(OUT, ">out_file.txt"); # opens this file for writing
foreach $line (@file_contents){
if($line eq "\n"){}
else{
print OUT $line;
}
}
close(OUT);
What would happen if you mistyped the name of the input file? The file would not be found and therefore no data
could be read from it. Execution would still continue, however, and a empty output file would be created.
When a I/O function executes, it returns a value of true if it has executed correctly. If not, it will return a
false value. In the example above, we have not collected thie returned values into a variable - we just ignored
them.
It's common practice to check the returned value from an I/O function and take corrective action if an error occurs.
In this case, we could change the open command for the input to:
$status = open(IN, "<line_file.dat"); # opens this file for reading
if(!$status) {
die "Could not open file!"; # die causes the program to immediate terminate
} # and print the message following it.
More commonly, this is abbreviated in this form:
open(IN, "<line_file.dat") || die "Could not open file!";
This is an example of a short-circuited boolean expression. If the part of the expression on the left side of the '||' (logical OR) is true, then the whole expression is true. There is no need to evaluate the part on the right side and it is not. However, if the expression part on the left is false (presumably because the file specified in the open statement could not be found), then the expression on the right still needs to evaluated. And when die is evaluated, it executes and script is terminated.