Putting File Handles in a Hash

P

pgl0338

I am trying to open an arbitrary number of files.
I hoped to put the file handles into a hash.
I am leaning-upon some code from pg. 194 of the Programming Perl 2nd edition
(FileHandle module)
In the following sample, the opens succeed (do not die), but the reads fail.

Thanks in advance!
pgl

#!/usr/bin/perl
use FileHandle;
&getInput;
foreach $iv (@files){
#.................................................#
# here's where I hope to eventually use the files #
#.................................................#
print "file: $filename{$iv}: ";
$line = <$FH{$iv}>;
print "$line";
}

sub getInput{
$lookingForFiles = 1;
while ($lookingForFiles){
print "file name > ";
chomp ($fn = <STDIN>);
if (-f $fn){
push @files, ($fn);
$FH{$fn} = new FileHandle
}else{
$lookingForFiles = 0;
}
}
foreach $name (@files){
$line = <$FH{$name}>;
print "line from $name:\n$line";
}
}
 
B

Ben Morrow

pgl0338 said:
I am trying to open an arbitrary number of files.
I hoped to put the file handles into a hash.
I am leaning-upon some code from pg. 194 of the Programming Perl 2nd
edition

You should really see if you can't get hold of a copy of the 3rd
edition: the 2nd is quite out-of-date now. And even then, you should
read the docs that come with perl and trust them more than any book.
In the following sample, the opens succeed (do not die), but the
reads fail.

Please elucidate further: I can't see any reason from what you've
given why they should fail. How do they fail? What (if any) error
messages do you get?
#!/usr/bin/perl

use warnings;
use strict;
use FileHandle;

FileHandle.pm is deprecated. If you *really* want OO syntax, use
IO::File; but now we have auto-vivifying lexical filehandles you don't
need it at all.

As you are using strictures, you will need

my (%FH, @files);

here.
&getInput;

Don't call subs with &. Either:

getInput();

or

use subs qw/getInput/;

getInput;

As a matter of style, stUdlyCaps tends to be frowned upon in the Perl
world.
foreach $iv (@files){

As you've added 'use strict;', you'll either need

for my $iv (@files) {

or simply

for (@files) {

and use $_. Again, using 'for' rather than 'foreach' is just a matter
of style (they are precisely identical).
#.................................................#
# here's where I hope to eventually use the files #
#.................................................#
print "file: $filename{$iv}: ";

Where is %filename set up? Don't you just mean "file: $iv: "?
$line = <$FH{$iv}>;

my $line = ...
print "$line";
}

sub getInput{
$lookingForFiles = 1;

my $lookingForFiles = 1;
while ($lookingForFiles){
print "file name > ";
chomp ($fn = <STDIN>);

chomp (my $fn = said:
if (-f $fn){

Don't do this. Just open it and see if it fails.
push @files, ($fn);
$FH{$fn} = new FileHandle

Err... I take it there's something missing here?
}else{
$lookingForFiles = 0;
}
}

I would re-write the whole loop thus:

while (<STDIN>) {
chomp;
open $FH{$_}, "< $_" or last;
push @files, $_;
}

or maybe I would add

use Errno;

at the top and then write the loop:

while (<STDIN>) {
chomp;
unless (open $FH{$_}, "< $_") {
$!{ENOENT} or die "can't open $_: $!";
last;
}
push @files, $_;
}

..
foreach $name (@files){
$line = <$FH{$name}>;

my $line = ...
print "line from $name:\n$line";
}
}

Ben
 
B

Brian McCauley

pgl0338 said:
$line = <$FH{$iv}>;

For historical reasons the <...> operator is sometimes shorthand for
readline(...) and sometiems for glob("...")

In the above case Perl is interpreting it as

$line = glob("$FH{$iv}");

The <...> operator is explained in perldoc perlop.

You need:

$line = readline $FH{$iv};

Or:

my $fh = $FH{$iv};
$line = <$fh>;

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
U

Uri Guttman

BM> For historical reasons the <...> operator is sometimes shorthand for
BM> readline(...) and sometiems for glob("...")

BM> In the above case Perl is interpreting it as

BM> $line = glob("$FH{$iv}");

BM> The <...> operator is explained in perldoc perlop.

BM> You need:

BM> $line = readline $FH{$iv};

or $line = $FH{$iv}->readline()

assuming a proper blessed handle ref is in there and not just a glob.

uri
 
C

ctcgag

pgl0338 said:
I am trying to open an arbitrary number of files.
I hoped to put the file handles into a hash.
I am leaning-upon some code from pg. 194 of the Programming Perl 2nd
edition (FileHandle module)
In the following sample, the opens succeed (do not die), but the reads
fail. ....
$line = <$FH{$name}>;

Read perldoc perlop. Since it is long, I'm posting the most relevant part:

That means `<$x>' is always a
readline() from an indirect handle, but `<$hash{key}>' is
always a glob(). That's because $x is a simple scalar
variable, but `$hash{key}' is not--it's a hash element.

Xho
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,824
Members
47,371
Latest member
Brkaa

Latest Threads

Top