A filehandle is a name for a file. The filehandle allows you to associate the filehandle name with a UNIX file and to use that filehandle to access the file. Perl allows you to create your own filehandles for input and output operations.
To create a filehandle and open a file, we use the open function. The open function returns a non-zero value if successful, and an undefined value if it fails. Like other types of variables (scalars, arrays, associative arrays, etc) filehandles have their own name space. It is recommended that all the filehandle names to be spelled in upper case letters.
open (INPUT_FILE,"myfile.txt");
....
close (INPUT_FILE);
Once a file was open, it will stay open until the end of the script or until the user uses the close function. The close function will close the file and remove the information that links the filehandle to the file.
There are three ways to open a file: to read, to write (which will erase the previous content of the file) or to append at the end of the file.
To read from a file, we have to open it first. To open a file to read from it, we use the open command as in the example above. It is sometimes necessary to check if the file was open successfully. For this one can use an if statement:
$setfile="input.txt";
if(!open(INPUT,$setfile)) {
print <<"EOT2";
<html> <head><title>ERROR:Opening File</title></head>
<body bgcolor=#ffffff>
<center><h1>ERROR: Opening File</h1></center>
<h3>Can not open file $setfile</h3>
Please check the settings and try again.
</body>
</html>
EOT2
exit;
}
OK! Now, that we opened the file, let's read some data. This is easily done by using the following statement
$my_variable = <INPUT>;
This will read a line from the file pointed by the filhandle INPUT and store it in the $my_variable scalar. But we have to check if we did not reach the end of the file (EOF). We can use the function eof which returns 1 if the next read operation on the given filehandle is at the end or if the file was not open.
if (!eof(INPUT)) {
$my_variable=<INPUT>;
}
Another way to read the data from a file (usefull if we need to read all the file) is using a while conditional loop.
while ($my_variable = <INPUT>) {
...
}
which will read all the lines, one by one, untill it reaches the end of the file.
To write to a file, we have to open it in a special way. We will use the same open function, but we will connect the filehandle to a special name. If, for example, the name of the file is ouput.txt, we will bound the filehandle to the file name >output.txt. The > sign will tell Perl that this filehandle will be used to write to the output.txt file. Remember that this operator will destroy the data existing in your file output.txt. If you just want to add a line at the end, you should open the file in append mode.
if(!open(MYOUTPUT,">output.txt")) {
print <<"EOT2";
<html> <head><title>ERROR:Opening File</title></head>
<body bgcolor=#ffffff>
<center><h1>ERROR: Opening File</h1></center>
<h3>Can not open the output file.</h3>
</body>
</html>
EOT2
exit;
}
Remember that in order to open a file for writing, we need to have write rights for that file. Thus, you should set the attributes to 666 for that file using the chmod UNIX command. You can test if you can write to a file in a Perl program by using a special if or unless statement
if (-w "myfile.txt") {
print "can open the file\n";
} else {
print "can not open the file\n";
}
The table below shows other special operators you can use with if or unless to check on files attributes or existance.
Operator | Meaning |
-r filename | True if filename is a readable file |
-w filename | True if filename is a writeable file |
-x filename | True if filename is an executable file |
-e filename | True if filename exists |
-z filename | True if filename has size 0 (empty file) |
Writing to a file is as easy as printing. The same rules apply. But instead of using just the print command followed by the text, we will also use the filehandle. Thus
print MYOUTPUT "This will go on the input file\n";
will print the text to the file pointed by MYOUTPUT filehalde. Note that if you are storing data that you will need to read later in the program, it is better to store one information on each line. This will ease you work later, when you will read the file. Instead of
print MYOUTPUT "$value1 $value2 $value3\n";
t is better to use
print MYOUTPUT "$value1\n$value2\n$value3\n";
If you need to print a lot of data to a file and you do not want to type the filhandle name, you can redirect all the printing to the file. This is useful when you want the same subroutine to be able to print on the screen or to a file. To do this we will use the select function. Select redirect the ouput to a filehandle and returns the existing filhandle. This is extremely important because we will need to restore the normal output at the end. Thus
if ($to_file) {
$oldhandle=select($newhandle);
}
print <<"EOT2";
<html> <head><title>ERROR:Opening File</title></head>
<body bgcolor=#ffffff>
<center><h1>ERROR: Opening File</h1></center>
<h3>Can not open the output file.</h3>
</body>
</html>
EOT2
if ($to_file) {
select($oldhandle);
}
will print to the screen (default output) if $to_file is 0 or
to the file pointed by $newhandle else. It will restore the original
output at the end.
To add data at the end of the file we have to open the file in append mode. This is done by adding two angle brackets to the name, compared to one for the write mode. Thus
if(!open(MYOUTPUT,">>output.txt")) {
print <<"EOT2";
<html> <head><title>ERROR:Opening File</title></head>
<body bgcolor=#ffffff>
<center><h1>ERROR: Opening File</h1></center>
<h3>Can not open the output file.</h3>
</body>
</html>
EOT2
exit;
}
will open the ouput.txt file in append mode. To add data all we have to do is to use the same print function we used in the write mode.
The seek function allows you to randoml;y access the file. This function is the same as the fseek standard i/o function in C. Seek allows you to move to some position within the file. The standard format is
seek(FILEHANDLE, BYTEOFFFSET, FILEPOSITION);
where FILEHANDLE is the filehandle to the file that we want to work with, BYTEOFFSET is the number of bytes we want to move from the given position, and POSITION represents the position from where we want to compute the BYTEOFFSET:
0 = Beginning of the file
1 = Current position in file
2 = End of the file
When using POSITION either 1 or 2, BYTEOFFSET can take negative numbers, otherwise it has to be positive.
seek (MYFILE,0,0); # moves to the beginning
of the file
seek (MYFILE,1,10); # moves 10 bytes ahead from current
postion
seek (MYFILE,2,-10); # moves 10 bytes backward from the end
of file
seek (MYFILE,2,0); # moves to the end of the file
Seek returns 1 if successful, 0 otherwise.
The tell function returns the current byte position in hte file and is used with seek to move to that position in the file.
This example shows how one can use files in a CGI program.