Writing
To write data to a file, you must first have a filehandle open for writing. Up till now, all open statements you have seen have opened the filehandle for reading only. The syntax for opening a file for writing is almost identical to that for reading:
open(filehandle, ">pathname") open(filehandle, ">>pathname")
The first syntax line should look familiar, except for the > in front of the pathname. The > signifies to Perl that the file specified at pathname should be overwritten with new data, that any existing data should be discarded, and that filehandle is open for writing. In the second example, >> tells Perl to open the file for writing but, if the file already exists, not to discard the contents but to append the new data to the end of it. Check out these examples:
# Overwrite existing data, if any open(NEWFH, ">output.txt") || die "Opening output.txt: $!"; # Simply append to whatever data may be there. open(APPFH, ">>logfile.txt") || die "Opening output.txt: $!";
NOTE
Until now, it's been almost impossible for your Perl programs to harm anything. Now that you know how to write to files, you must be very careful to write only to files that you mean to change. On systems in which the operating system files are vulnerable (Windows 95/98, Mac), you can damage your operating system by carelessly writing to files. Be very aware of what files you are writing to. Recovering the data in files accidentally opened with > is nearly impossible. Cleaning out data in files opened accidentally with >> also is difficult, so be careful.
When you're done with a filehandle opened for writing, closing the filehandle is especially important. Your operating system doesn't commit data to disk as you write it; it buffers the data up and writes it occasionally. The close function notifies the operating system that you are done writing and that the data should be moved to permanent storage on disk:
close(NEWFH); close(APPFH);
If your program terminates with exit, or simply "falls off" the end, any written but not-yet-flushed information in filehandles is committed (written out to the file) as if you had closed the filehandles yourself.
After you've opened the filehandle for writing, actually putting data in the file is easy, and you're already familiar with the print function. Until now, you've been using print to simply display data to the screen. The print function is actually used for writing to any filehandle. The syntax for printing to filehandles is as follows:
print filehandle LIST
filehandle is the filehandle you want the data to be written to, and LIST is the list of things you want written.
In the print syntax, notice that no comma appears between the filehandle name and the list; this point is important. Inside the list, commas are used to separate items, as you've done until now. The lack of a comma between the filehandle and list signifies to Perl that the token following print is a filehandle and not the first element in the list. If you include this comma and have Perl's warnings turned on, Perl warns you with the following message: No comma allowed after filehandle.
Now consider the following:
open(LOGF, ">>logfile") || die "$!"; if (! print LOGF "This entry was written at", scalar(localtime), "\n" ) { warn "Unable to write to the log file: $!"; } close(LOGF);
In this snippet, the file named logfile is opened for appending. The print statement writes a message to the LOGF filehandle. The return value from print is checked, and if false (meaning that the log entry could not be printed), a warning is issued. The filehandle is then closed.
You can have multiple filehandles open for reading and writing at the same time, as this snippet demonstrates:
open(SOURCE, "sourcefile") || die "$!"; open(DEST, ">destination") || die "$!"; @contents=<SOURCE>; # Slurp in the source file. print DEST @contents; # Write it out to the destination close(DEST); close(SOURCE);
This snippet implements a simple file copy. As a matter of fact, you can do the read and the write at the same time and shorten the routine, just a little:
print DEST <SOURCE>;
Because print expects a list as an argument, <SOURCE> is evaluated in a list context. When the angle operator is evaluated in a list context, the entire file is read in and then printed to the filehandle DEST.