Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

A Few Questions About IO::File

by rpetrelli (Novice)
on Mar 18, 2013 at 13:55 UTC ( [id://1024044]=perlquestion: print w/replies, xml ) Need Help??

rpetrelli has asked for the wisdom of the Perl Monks concerning the following question:

Hi there, I'm trying out the module IO::File and one thing confuses me: how do I properly close the file? The IO::File synopsis section demonstrates two ways to close the file either with:

use IO::File; my $fh = IO::File->new('foo', 'r'); # do something with $fh undef $fh;
or with:
# continuing from above $fh->close;

Coming from python background, the second method fits better in my brain, but I'm not sure if this is the correct way especially since the $fh variable is still defined:

# The output is something like IO::File=GLOB(yadda yadda) print "$fh" if defined $fh;

Somewhat related, I tried this code to get a list of lines from a file:

my @lines = IO::File->new('foo')->getlines;

It's very convenient, but this isn't mentioned anywhere in the doc and I'm not sure whether this has any negative side effects.

Replies are listed 'Best First'.
Re: A Few Questions About IO::File
by hdb (Monsignor) on Mar 18, 2013 at 14:18 UTC

    According to module documentation on IO::File on CPAN undef $fh closes the file automatically. In contrast to Python, in Perl there is more than one way to do it. So both of your options are valid.

    getlines comes from IO::Handle and is safe in list context according to its documentation.

    For every complex problem there is an answer that is clear, simple, and wrong. H. L. Mencken

      Thanks for the prompt answer. So both methods are valid and safe? Because like I mentioned previously, the $fh->close method fits better in my brain.

      I read the IO::File documentation. While I understand that getlines is supposed to be used in list context, using it directly by chaining the methods is not mentioned in there and I'm wondering the safety of using such method.

        "I read the IO::File documentation. While I understand that getlines is supposed to be used in list context, using it directly by chaining the methods is not mentioned in there and I'm wondering the safety of using such method."

        File handles are scalars, so you can push them onto arrays like this:

        push @all_handles, $fh;

        And pop them off like this:

        my $fh = pop @all_handles;

        And you can loop through an array of filehandles like this:

        for my $fh (@all_handles) { ...; # do something with $fh }

        And you can get a count of how many filehandles are in your array of filehandles like this:

        my $count_filehandles = @all_handles;

        There is no need to mention any of the above in the IO::File documentation because this is simply how arrays work in Perl. The fact that they're arrays of filehandles is not significant - they could be arrays of integers, or XML documents, or whatever.

        Similarly, there's no need to mention in the IO::File documentation that methods which return an object can be chained. That's just how method calls work in Perl (indeed, in most programming languages that support OO).

        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
        When you chain the commands you will not get a handle to close the file. I have to admit that I am not so sure myself when the file will get closed...
Re: A Few Questions About IO::File
by talexb (Chancellor) on Mar 18, 2013 at 15:06 UTC

    I get how $fh->close fits your brain better, but you can also consider that the file handle will be closed when the variable holding the filehandle goes out of scope.

    So you could do something like this:

    use IO::File; { my $fh = IO::File->new('foo', 'r'); # do something with $fh } # The file handle has been automagically closed!
    My background is C, so I usually follow an open command with a close command, then go back up and do everything else, but you can use a block to effect the same thing.

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

      I see, thanks for the clarification.

Re: A Few Questions About IO::File
by topher (Scribe) on Mar 18, 2013 at 17:32 UTC

    There's been a good bit of decent discussion on this, and I'm guessing you've gotten most of your questions answered. One thing I didn't really see mentioned is a bit on the "why" of it.

    When you create a new IO::File object, you are, obviously, creating an object for your filehandle and assigning it to a variable. After you finish with it, you can call $fh_var->close; to explicitly close your file. Personally, I'm a big fan of this, as it makes your intentions clear and it's a good habit to clean up after yourself.

    If you undef the variable, you get the same behavior as the variable going out of scope, which is that Perl will automatically clean up (the equivalent of a DESTROY() method) after you and close the file; as the object no longer has any references to it, there is no way to access the file, so it is "garbage collected", so to speak.

    Neither the the explicit close function nor the variable undef is really better or worse than the other, although they do offer different trade-offs. For example, if you do an explicit close, you can re-use for IO::File object to open a new file. If you undefine the object reference, you will need a new object if you wanted to open a new file.

    Christopher Cashell
Re: A Few Questions About IO::File (be explicit)
by Anonymous Monk on Mar 18, 2013 at 15:04 UTC

    You can't go wrong with being explicit (close), it really depends on the rest of the code :)

    undef can work, provided there is only ever a single reference / copy of filehandle, but won't close if reference count goes up  my $copy = $fh; close will always close -- explicit is good (q:gimme some? a: some what? q: that over there; q: to the left; q: lefter; :)

    But if you write in narrow scopes

    if( open my($fh) ... ){ 1 2 3 4 5 }

    implicit undef can work, as can explicit undef, as can explicit close

    Which is better?  print $fh $str or die $!; close $fh or die $! ? use autodie ? Whatever fits?

    It's very convenient, but this isn't mentioned anywhere in the doc and I'm not sure whether this has any negative side effects.

    Often the doc is a start of a reading list, not just Ctrl+F for "close" :)

    IO::File -> IO::File inherits from IO::Handle and IO::Seekable -> SEE ALSO perlfunc, I/O Operators in perlop, IO::Handle, IO::Seekable, IO::Dir

    IO::Handle lists the close method

    the close function which you can also use is listed at perlfunc#close , #Input and output functions, close

      :) Ha, getlines is also documented in IO::Handle

      See my reply to hdb. I already read the IO::Handle (oops just realized I had a typo there, how do you edit your post anyway?), but what perplexes me is the chaining methods part.

Re: A Few Questions About IO::File
by ikegami (Patriarch) on Mar 19, 2013 at 18:57 UTC

    From ??? up to 5.12, file handles were objects of IO::Handle (unless you reblessed them). You needed to load IO::Handle or IO::File yourself if you want to use its methods.

    From 5.12 up to 5.14, file handles were objects of IO::File (unless you reblessed them). You needed to load IO::Handle or IO::File yourself if you want to use its methods.

    From 5.14 on, file handles are objects of IO::File (unless you reblessed them). IO::Handle and IO::File are automatically loaded on demand.

    This is a supported feature.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1024044]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-04-19 05:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found