Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

tripping over filehandle / subroutine usage

by chexmix (Hermit)
on Dec 21, 2012 at 20:56 UTC ( #1009957=perlquestion: print w/ replies, xml ) Need Help??
chexmix has asked for the wisdom of the Perl Monks concerning the following question:

Holidayish Greetings, Monks --

Today I had to whip up a quick script, which typically makes me nervous, and I noticed something that to my still-baby-Perl eyes seemed ... well, interesting, I guess.

I had to create some reports from a couple of tab-delimited text files, so as I usually do, I opened filehandles to them:

open (my $INFILE_1, '<', 'name_o_file.txt') || croak "Cannot open input file: $!\n";

... and same deal for a second file / handle.

I then created subroutines to create the reports, and tried passing the filehandles into the subroutines. It worked fine for the first subroutine, but when I passed the same filehandles to a SECOND subroutine ... nothing happened. No output. It was as though I had not called that second subroutine at all.

I only explicitly closed the filehandles after the second subroutine call.

Just because I got desperate, I tried creating TWO MORE filehandles to the same files, and passing those to the second subroutine. This worked.

What is happening here? Do filehandles get auto-closed when they are passed to a subroutine and the subroutine returns?

(this is probably really basic, but somehow I have never encountered it before).

UPDATE: of course, I should _think_ before I post (and post code as well)

Here is what doesn't work:

open(my $CDA1, '<', 'cda1_raw.txt') || croak "Cannot open input file 1: $!\n"; open(my $CDA2, '<', 'cda2_raw.txt') || croak "Cannot open input file 2: $!\n"; report_one($CDA1, 'cda1_boffle.txt'); report_one($CDA2, 'cda2_boffle.txt'); report_two($CDA1, $CDA2, $dbh); close $CDA1; close $CDA2;

And here is what worked:

open(my $CDA1, '<', 'cda1_raw.txt') || croak "Cannot open input file 1: $!\n"; open(my $CDA2, '<', 'cda2_raw.txt') || croak "Cannot open input file 2: $!\n"; report_one($CDA1, 'cda1_boffle.txt'); report_one($CDA2, 'cda2_boffle.txt'); open(my $CDA3, '<', 'cda1_raw.txt') || croak "Cannot open input file: $!\n"; open(my $CDA4, '<', 'cda2_raw.txt') || croak "Cannot open input file: $!\n"; report_three ($CDA3, $CDA4, $dbh); close $CDA1; close $CDA2; close $CDA3; close $CDA4;
And here is the report_one sub:
sub report_one { my ($input_handle, $output_name) = @_; open(my $OUT, '>', "$output_name") || croak "Cannot open output file: $!\n"; my $current_host = ""; my %host_counts; my @rows = (<$input_handle>); foreach ( @rows ) { my ($date, $time, $host, $bytes, $bytes_sec, $server) += split /\t/; if ( ( $bytes < 1000000 ) || ( $bytes == $bytes_sec ) +) { next; } if ( $host eq $current_host ) { $host_counts{$host}{bytes} += $bytes; $host_counts{$host}{speed} += $bytes_sec; $host_counts{$host}{count}++; } else { $host_counts{$host}{bytes} = $bytes; $host_counts{$host}{speed} = $bytes_sec; $host_counts{$host}{count} = 1; } $current_host = $host; } foreach my $heauxst ( keys %host_counts ){ my $avg_speed = int( $host_counts{$heauxst}{speed} / $ +host_counts{$heauxst}{count} ); print $OUT "$heauxst\t$host_counts{$heauxst}{bytes}\t$ +avg_speed\n"; } close $OUT; return; }

Comment on tripping over filehandle / subroutine usage
Select or Download Code
Replies are listed 'Best First'.
Re: tripping over filehandle / subroutine usage
by LanX (Canon) on Dec 21, 2012 at 21:43 UTC
    just a guess:

    if your FH is at EOF after the first subroutine you should reset the position to start using seek before expecting to read again in another sub.

    UPDATE:

    ok, now that you updated code it seems like my guess was right:

    my @rows = (<$input_handle>);

    exhausts your filehandle.

    BTW you should consider working with something like

    while ( my $line = <$input_handle>) {
    to read line by line, when working with large files, because otherwise you're consuming lots of RAM.

    Cheers Rolf

Re: tripping over filehandle / subroutine usage
by roboticus (Chancellor) on Dec 21, 2012 at 21:04 UTC

    chexmix:

    What you want to do should work. But you don't show the code that's failing, so I can't tell you why it fails. But I do it often enough.

    $ perl t.pl $ cat out.txt bob $ cat t.pl #!/usr/bin/perl use strict; use warnings; foo("bob"); sub foo { my $txt = shift; open my $FH, '>', 'out.txt' or die $!; bar($FH, $txt); } sub bar { my ($FH, $msg) = @_; baz($FH, $msg); } sub baz { my ($FH, $message) = @_; print $FH $message; }

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      normally I avoid typing lexicals $filehandles in uppercase.

      To much risk to confuse them with bareword FILEHANDLES...

      Cheers Rolf

Re: tripping over filehandle / subroutine usage
by LanX (Canon) on Dec 21, 2012 at 21:00 UTC
    > Do filehandles get auto-closed when they are passed to a subroutine and the subroutine returns?

    no!

    > (this is probably really basic, but somehow I have never encountered it before).

    and we can't tell what you're doing ... because you don't provide much reproducible code. :)

    > What is happening here?

    You have a bug in the code you're hiding from us!

    Cheers Rolf

    ) (X-Lan activating his magical psy abilities to read foreign harddisks =)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1009957]
Approved by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (12)
As of 2015-07-29 09:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (263 votes), past polls