11.2. Opening a FilehandleSo we see that Perl provides three filehandles -- STDIN, STDOUT, and STDERR -- which are automatically open to files or devices established by the program's parent process (probably the shell). When you need other filehandles, use the open operator to tell Perl to ask the operating system to open the connection between your program and the outside world. Here are some examples: open CONFIG, "dino"; open CONFIG, "<dino"; open BEDROCK, ">fred"; open LOG, ">>logfile"; The first one opens a filehandle called CONFIG to a file called dino. That is, the (existing) file dino will be opened and whatever it holds will come into our program through the filehandle named CONFIG. This is similar to the way that data from a file could come in through STDIN if the command line had a shell redirection like <dino. In fact, the second example uses exactly that sequence. The second does the same as the first, but the less-than sign explicitly says "this filename is to be used for input," even though that's the default.[248]
Although you don't have to use the less-than sign to open a file for input, we include that because, as you can see in the third example, a greater-than sign means to create a new file for output. This opens the filehandle BEDROCK for output to the new file fred. Just as when the greater-then sign is used in shell redirection, we're sending the output to a new file called fred. If there's already a file of that name, we're asking to wipe it out and replace it with this new one. The fourth example shows how two greater-than signs may be used (again, as the shell does) to open a file for appending. That is, if the file already exists, we will add new data at the end. If it doesn't exist, it will be created in much the same way as if we had used just one greater-than sign. This is handy for log files; your program could write a few lines to the end of a log file each time it's run. So that's why the fourth example names the filehandle LOG and the file logfile. You can use any scalar expression in place of the filename specifier, although typically you'll want to be explicit about the direction specification: my $selected_output = "my_output"; open LOG, "> $selected_output"; Note the space after the greater-than. Perl ignores this,[249] but it keeps unexpected things from happening if $selected_output were ">passwd" for example (which would make an append instead of a write).
We'll see how to use these filehandles later in this chapter. 11.2.1. Closing a FilehandleWhen you are finished with a filehandle, you may close it with the close operator like this: close BEDROCK; Closing a filehandle tells Perl to inform the operating system that we're all done with the given data stream, so any last output data should be written to disk in case someone is waiting for it.[250]
Perl will automatically close a filehandle if you reopen it (that is, if you reuse the filehandle name in a new open) or if you exit the program.[251] Because of this, many simple Perl programs don't bother with close. But it's there if you want to be tidy, with one close for every open. In general, it's best to close each filehandle soon after you're done with it, though the end of the program often arrives soon enough.[252]
11.2.2. Bad FilehandlesPerl can't actually open a file all by itself. Like any other programming language, Perl can merely ask the operating system to let us open a file. Of course, the operating system may refuse, because of permission settings, an incorrect filename, or other reasons. If you try to read from a bad filehandle (that is, a filehandle that isn't properly open), you'll see an immediate end-of-file. (With the I/O methods we'll see in this chapter, end-of-file will be indicated by undef in a scalar context or an empty list in a list context.) If you try to write to a bad filehandle, the data is silently discarded. Fortunately, these dire consequences are easy to avoid. First of all, if we ask for warnings with -w, Perl will generally be able to tell us with a warning when it sees that we're using a bad filehandle. But even before that, open always tells us if it succeeded or failed, by returning true for success or false for failure. So you could write code like this: my $success = open LOG, ">>logfile"; # capture the return value unless ($success) { # The open failed ... } Well, you could do it like that, but there's another way that we'll see in the next section. Copyright © 2002 O'Reilly & Associates. All rights reserved. |
|