File handling with subroutines and references

Discussion in 'Perl Misc' started by Eric Martin, Jan 17, 2006.

  1. Eric Martin

    Eric Martin Guest

    I am processing multiple files and am trying to create routines that
    will efficiently read/write files. I am using variable names for the
    FILEHANDLE to prevent any conflicts during processing (Is this a good
    practice or is there a *better* way?).

    use strict; use warnings;
    no strict 'refs';
    use Fcntl qw:)DEFAULT :flock);

    sub file_open {
    my ($fh, $file, $mode) = @_;
    open($fh, "$mode $file") || die("Cannot open $file: $!");
    flock($fh, LOCK_EX);
    return \*$fh;
    }

    sub file_close {
    my $fh = shift;
    close($fh);
    }

    my $file = "data.txt";
    my $fh = file_open("TEST_OUT", $file, '+<');
    my $out = file_open("TEST_IN", "data_out.txt", '+>');
    while (<$fh>) {
    # process data
    # ...
    print $out $_;
    }
    file_close($out);
    file_close($fh);

    __END__

    I tried:
    sub file_open {
    my ($fh, $file, $mode) = @_;
    my $filehandle = do { local *$fh }; # <-- ADDED
    open($filehandle, "$mode $file") || die("Cannot open $file: $!");
    flock($filehandle, LOCK_EX);
    return \*$filehandle;
    }

    which I saw in an example. I've seen it used for file "slurping", but I
    am not sure if it is something I should use. My understanding is that
    it is used to make the FILEHANDLE local, but in the context that I am
    using, it doesn't seem necessary.

    I know there are modules out there to use, but I am not using them
    because I need the code to work with the standard 5.004 Perl install.

    I'm looking for any code/design comments. Anything that I'm not doing
    or that I should be doing?

    Thanks,
    Eric
     
    Eric Martin, Jan 17, 2006
    #1
    1. Advertising

  2. Eric Martin

    Guest

    "Eric Martin" <> wrote:
    > I am processing multiple files and am trying to create routines that
    > will efficiently read/write files. I am using variable names for the
    > FILEHANDLE to prevent any conflicts during processing


    > (Is this a good
    > practice or is there a *better* way?).
    >
    > use strict; use warnings;
    > no strict 'refs';


    Why that? Is it necessary for what you are doing here?

    > use Fcntl qw:)DEFAULT :flock);
    >
    > sub file_open {
    > my ($fh, $file, $mode) = @_;
    > open($fh, "$mode $file") || die("Cannot open $file: $!");
    > flock($fh, LOCK_EX);


    You should check the success (return value) of flock:

    flock($fh, LOCK_EX) or die "$file: $!";

    > return \*$fh;
    > }
    >
    > sub file_close {
    > my $fh = shift;
    > close($fh);


    # Not as important to check as open or flock,
    # but may as well do it anyway!
    close ($fh) or die $!;

    > }


    >
    > I know there are modules out there to use, but I am not using them
    > because I need the code to work with the standard 5.004 Perl install.


    Ah, I had started writing a lot more comments until I noticed this part. I
    no longer remember all the pitfalls from the bad old days of 5.004, so I'll
    just shut up now.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Jan 18, 2006
    #2
    1. Advertising

  3. Eric Martin

    Eric Martin Guest

    wrote:
    > "Eric Martin" <> wrote:
    >> I am processing multiple files and am trying to create routines that
    >> will efficiently read/write files. I am using variable names for the
    >> FILEHANDLE to prevent any conflicts during processing

    >
    >> (Is this a good
    >> practice or is there a *better* way?).
    >>
    >> use strict; use warnings;
    >> no strict 'refs';

    >
    > Why that? Is it necessary for what you are doing here?


    Are you asking about the no strict 'refs'?
    Not using it gives:
    "Can't use string ("TEST_OUT") as a symbol ref while "strict refs" in
    use at ..."

    >
    >> use Fcntl qw:)DEFAULT :flock);
    >>
    >> sub file_open {
    >> my ($fh, $file, $mode) = @_;
    >> open($fh, "$mode $file") || die("Cannot open $file: $!");
    >> flock($fh, LOCK_EX);

    >
    > You should check the success (return value) of flock:
    >
    > flock($fh, LOCK_EX) or die "$file: $!";
    >


    True.

    >> return \*$fh;
    >> }
    >>
    >> sub file_close {
    >> my $fh = shift;
    >> close($fh);

    >
    > # Not as important to check as open or flock,
    > # but may as well do it anyway!
    > close ($fh) or die $!;
    >


    True again. =)

    >> }

    >
    >> I know there are modules out there to use, but I am not using them
    >> because I need the code to work with the standard 5.004 Perl install.

    >
    > Ah, I had started writing a lot more comments until I noticed this part. I
    > no longer remember all the pitfalls from the bad old days of 5.004, so I'll
    > just shut up now.
    >


    LOL. My program will be used on a variety of OS/Web server/Perl servers,
    so I just want to make the code as backwards compatible as possible.

    I was hoping that people with more IO familiarity could check the
    efficiency/scalability of the code.

    Thanks,
    Eric
     
    Eric Martin, Jan 18, 2006
    #3
  4. Eric Martin wrote:

    > I am using variable names for the
    > FILEHANDLE to prevent any conflicts during processing (Is this a good
    > practice or is there a *better* way?).


    IMHO, this is a very good practice. But you are using it in a strange way.

    > sub file_open {
    > my ($fh, $file, $mode) = @_;
    > open($fh, "$mode $file") || die("Cannot open $file: $!");
    > flock($fh, LOCK_EX);
    > return \*$fh;
    > }

    ....

    > my $file = "data.txt";
    > my $fh = file_open("TEST_OUT", $file, '+<');


    Get rid of that first argument to the function call. Simply call the function
    with the file name and the desired open mode, create the file handle in the
    subroutine and then return it:

    sub file_open {
    my ( $name, $mode ) = @_;
    open my $handle, "$mode $name";
    return $handle;
    }
     
    Manni Heumann, Jan 18, 2006
    #4
  5. Eric Martin <> wrote:
    > wrote:
    >> "Eric Martin" <> wrote:


    >>> no strict 'refs';

    >>
    >> Why that? Is it necessary for what you are doing here?

    >
    > Are you asking about the no strict 'refs'?
    > Not using it gives:
    > "Can't use string ("TEST_OUT") as a symbol ref while "strict refs" in
    > use at ..."



    When your car is making a funny noise, you count it as "fixed"
    after turning up the volume on your radio?

    Masking bugs is not the same as fixing bugs.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jan 18, 2006
    #5
  6. Eric Martin <> wrote:

    > because I need the code to work with the standard 5.004 Perl install.



    Why do you need to use a perl that is over 8 years old?


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Jan 18, 2006
    #6
  7. Eric Martin wrote:
    > wrote:
    > > "Eric Martin" <> wrote:
    > >> I am processing multiple files and am trying to create routines that
    > >> will efficiently read/write files. I am using variable names for the
    > >> FILEHANDLE to prevent any conflicts during processing


    There is no conflict if two anonymous file handles have the same name.
    (If you'll excuse the oxymoron).

    > >
    > >> no strict 'refs';

    > >
    > > Why that? Is it necessary for what you are doing here?

    >
    > Are you asking about the no strict 'refs'?
    > Not using it gives:
    > "Can't use string ("TEST_OUT") as a symbol ref while "strict refs" in
    > use at ..."


    You should always disable strictures in the smallest applicable scope.

    my $fh = "TEST_OUT";
    my $filehandle = do { no strict 'refs'; local *$fh };

    $filehandle now contains an anonymous file handle that _thinks_ its
    name is TEST_OUT.

    If you execute the same code again you'll get _another_ anonymous file
    handle that also thinks its name is TEST_OUT.

    For most purposes it doesn't matter what an anonymous file handle
    thinks its name is. (Occasionally it will be displayed in debugging
    info but that's about all).

    So people usually just write something like.

    my $filehandle = do { local *FH };

    Actually I prefer to use a GLOBref rather than a GLOB. The exact
    semantics of scalar variables that happen to hold GLOBs are just too
    weird.

    my $filehandle = \do { local *FH };


    That said... why are you using such an old Perl. All this is a lot
    simpler from 5.6.1 onwards where open() et al autovivify.
     
    Brian McCauley, Jan 18, 2006
    #7
  8. Eric Martin

    Eric Martin Guest

    Tad McClellan wrote:
    > Eric Martin <> wrote:
    >> wrote:
    >>> "Eric Martin" <> wrote:

    >
    >>>> no strict 'refs';
    >>> Why that? Is it necessary for what you are doing here?

    >> Are you asking about the no strict 'refs'?
    >> Not using it gives:
    >> "Can't use string ("TEST_OUT") as a symbol ref while "strict refs" in
    >> use at ..."

    >
    >
    > When your car is making a funny noise, you count it as "fixed"
    > after turning up the volume on your radio?
    >


    Thanks for the analogy, but I don't think it really helps me with my
    question.

    > Masking bugs is not the same as fixing bugs.


    I'm not sure if you read my question...I wanted to use variables as
    filehandle names. I took a shot at doing it and obviously I felt I
    needed advice, or I wouldn't have asked the question.

    I found the suggestion to use no strict 'refs' on a website talking
    about passing a scalar to use as a filehandle name. So...I appreciate
    you taking the time to respond, I just wish it was more to steer me in
    the right direction as opposed to just telling me it's wrong.

    Thanks,
    Eric
     
    Eric Martin, Jan 18, 2006
    #8
  9. Eric Martin

    Eric Martin Guest

    Manni Heumann wrote:
    > Eric Martin wrote:
    >
    >> I am using variable names for the
    >> FILEHANDLE to prevent any conflicts during processing (Is this a good
    >> practice or is there a *better* way?).

    >
    > IMHO, this is a very good practice. But you are using it in a strange way.
    >


    Fair enough =)

    >> sub file_open {
    >> my ($fh, $file, $mode) = @_;
    >> open($fh, "$mode $file") || die("Cannot open $file: $!");
    >> flock($fh, LOCK_EX);
    >> return \*$fh;
    >> }

    > ...
    >
    >> my $file = "data.txt";
    >> my $fh = file_open("TEST_OUT", $file, '+<');

    >
    > Get rid of that first argument to the function call. Simply call the function
    > with the file name and the desired open mode, create the file handle in the
    > subroutine and then return it:
    >
    > sub file_open {
    > my ( $name, $mode ) = @_;
    > open my $handle, "$mode $name";
    > return $handle;
    > }


    Makes sense...thanks for the suggestions.

    -Eric
     
    Eric Martin, Jan 18, 2006
    #9
  10. Eric Martin

    Paul Lalli Guest

    Eric Martin wrote:
    > Thanks for the analogy, but I don't think it really helps me with my
    > question.


    That's because your question is faulty.

    > > Masking bugs is not the same as fixing bugs.

    >
    > I'm not sure if you read my question...I wanted to use variables as
    > filehandle names.


    *Why*? I've read this thread three or four times, and I have yet to
    figure out *why* you think you need to store a "name" of a filehandle
    variable in another variable. What makes you think this is necessary?
    If you want a file handle reference, just make a reference. It does
    not need a name of any kind.

    See also: perldoc -q "variable name"

    Paul Lalli
     
    Paul Lalli, Jan 18, 2006
    #10
  11. Eric Martin <> writes:
    > Manni Heumann wrote:
    > > Get rid of that first argument to the function call. Simply call the
    > > function with the file name and the desired open mode, create the
    > > file handle in the subroutine and then return it:
    > > sub file_open {
    > > my ( $name, $mode ) = @_;
    > > open my $handle, "$mode $name";
    > > return $handle;
    > > }

    >
    > Makes sense...thanks for the suggestions.


    I'm at least 90% sure that syntax, while much better than what you
    were using, doesn't work under 5.004, which you specified. Of course,
    I don't happen to have an 8-year-old copy of perl to test that with,
    but I'm reasonably positive it worked as of 5.6 or so.

    -=Eric
     
    Eric Schwartz, Jan 18, 2006
    #11
  12. Eric Martin

    Eric Martin Guest

    Tad McClellan wrote:
    > Eric Martin <> wrote:
    >
    >> because I need the code to work with the standard 5.004 Perl install.

    >
    >
    > Why do you need to use a perl that is over 8 years old?


    *I* don't need to, but the people using the program might. My options
    are to code to work with 5.004, or require a more recent version of
    Perl. I'll evaluate the latter.

    Thanks,
    Eric
     
    Eric Martin, Jan 18, 2006
    #12
  13. Eric Martin

    Eric Martin Guest

    Brian McCauley wrote:
    > Eric Martin wrote:
    >> wrote:
    >>> "Eric Martin" <> wrote:
    >>>> I am processing multiple files and am trying to create routines that
    >>>> will efficiently read/write files. I am using variable names for the
    >>>> FILEHANDLE to prevent any conflicts during processing

    >
    > There is no conflict if two anonymous file handles have the same name.
    > (If you'll excuse the oxymoron).
    >


    Good to know, thanks.

    >>>> no strict 'refs';
    >>> Why that? Is it necessary for what you are doing here?

    >> Are you asking about the no strict 'refs'?
    >> Not using it gives:
    >> "Can't use string ("TEST_OUT") as a symbol ref while "strict refs" in
    >> use at ..."

    >
    > You should always disable strictures in the smallest applicable scope.
    >
    > my $fh = "TEST_OUT";
    > my $filehandle = do { no strict 'refs'; local *$fh };
    >
    > $filehandle now contains an anonymous file handle that _thinks_ its
    > name is TEST_OUT.
    >
    > If you execute the same code again you'll get _another_ anonymous file
    > handle that also thinks its name is TEST_OUT.
    >
    > For most purposes it doesn't matter what an anonymous file handle
    > thinks its name is. (Occasionally it will be displayed in debugging
    > info but that's about all).
    >
    > So people usually just write something like.
    >
    > my $filehandle = do { local *FH };
    >
    > Actually I prefer to use a GLOBref rather than a GLOB. The exact
    > semantics of scalar variables that happen to hold GLOBs are just too
    > weird.
    >
    > my $filehandle = \do { local *FH };
    >


    Thanks for all of the suggestions.

    >
    > That said... why are you using such an old Perl. All this is a lot
    > simpler from 5.6.1 onwards where open() et al autovivify.
    >


    I'll look into requiring a more recent version.

    Thanks,
    Eric
     
    Eric Martin, Jan 18, 2006
    #13
  14. Eric Martin

    Eric Martin Guest

    Paul Lalli wrote:
    > Eric Martin wrote:
    >> Thanks for the analogy, but I don't think it really helps me with my
    >> question.

    >
    > That's because your question is faulty.


    How? I asked to question in order to determine if what I was trying to
    do was faulty. Does that make the question or the approach faulty?

    >
    >>> Masking bugs is not the same as fixing bugs.

    >> I'm not sure if you read my question...I wanted to use variables as
    >> filehandle names.

    >
    > *Why*? I've read this thread three or four times, and I have yet to
    > figure out *why* you think you need to store a "name" of a filehandle
    > variable in another variable. What makes you think this is necessary?
    > If you want a file handle reference, just make a reference. It does
    > not need a name of any kind.
    >


    Because I obviously didn't completely understand filehandles and their
    names. With some helpful suggestions, I have been able to understand
    what is going on and that I don't need to *name* the filehandles.

    > See also: perldoc -q "variable name"
    >


    Thanks.

    -Eric
     
    Eric Martin, Jan 18, 2006
    #14
  15. Eric Martin

    Paul Lalli Guest

    Eric Martin wrote:
    > Paul Lalli wrote:
    > > Eric Martin wrote:
    > >> Thanks for the analogy, but I don't think it really helps me with my
    > >> question.

    > >
    > > That's because your question is faulty.

    >
    > How? I asked to question in order to determine if what I was trying to
    > do was faulty. Does that make the question or the approach faulty?


    The question was faulty because you were not asking for help with your
    *actual* goal. You were asking for help with something you wanted to
    do to achieve your goal. This is traditionally known as the XY
    problem. You want to do X, you think you need to do Y to do X, so you
    ask for help with Y instead of with X.

    > > *Why*? I've read this thread three or four times, and I have yet to
    > > figure out *why* you think you need to store a "name" of a filehandle
    > > variable in another variable. What makes you think this is necessary?
    > > If you want a file handle reference, just make a reference. It does
    > > not need a name of any kind.
    > >

    >
    > Because I obviously didn't completely understand filehandles and their
    > names. With some helpful suggestions, I have been able to understand
    > what is going on and that I don't need to *name* the filehandles.


    Right. You didn't understand filehandles, and made several assumptions
    about them. Next time, don't make the assumptions, ask the questions
    straight out.

    Paul Lalli
     
    Paul Lalli, Jan 18, 2006
    #15
  16. Manni Heumann wrote:

    > open my $handle, "$mode $name";


    That makes no sense.

    Autovivifcation of filehandles feature of open() was introduced _after_
    the removal misfeature that required the mode and name arguments to be
    combined into a single string.

    If you can assume that open() supports autovivifcation then you can
    assume it support mode and name as separate aruments.
     
    Brian McCauley, Jan 18, 2006
    #16
  17. Eric Martin

    Eric Martin Guest

    Brian McCauley wrote:
    > Manni Heumann wrote:
    >
    >> open my $handle, "$mode $name";

    >
    > That makes no sense.
    >
    > Autovivifcation of filehandles feature of open() was introduced _after_
    > the removal misfeature that required the mode and name arguments to be
    > combined into a single string.
    >
    > If you can assume that open() supports autovivifcation then you can
    > assume it support mode and name as separate aruments.
    >


    Hmm...according to the perl561delta, it looks like autovivification and
    the 3 argument open() were added in 5.6.1:
    http://perldoc.perl.org/perl561delta.html#File-and-directory-handles-can-be-autovivified

    Either way, your second statement would be correct =)

    -Eric
     
    Eric Martin, Jan 19, 2006
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ReaprZero

    References and subroutines

    ReaprZero, Dec 4, 2003, in forum: Perl
    Replies:
    1
    Views:
    450
    Gunnar Hjalmarsson
    Dec 4, 2003
  2. Ketema

    References Subroutines and Arrays

    Ketema, Mar 5, 2004, in forum: Perl Misc
    Replies:
    2
    Views:
    142
  3. Rainer Weikusat
    Replies:
    1
    Views:
    136
    Rainer Weikusat
    Jan 4, 2014
  4. Peter J. Holzer
    Replies:
    1
    Views:
    85
    Rainer Weikusat
    Jan 7, 2014
  5. Jürgen Exner
    Replies:
    9
    Views:
    97
    Charlton Wilbur
    Jan 13, 2014
Loading...

Share This Page