recursive filehandle

W

Wijnand Nijs

Hello,

I have a problem with the next recursive subroutine used in a mailing
script:

#-----------------------
# sub built_tolist
# format lines listfiles:
# referense to a listfile = |0|nijs-bruls|
# subscribed address = |1|firstname|surname|mailaddress|etc.
# unsubscribed address = |2|firstname|surname|mailaddress|etc.
#-----------------------

sub built_tolist($) {
local (*FILE);
my $Listfile = shift;
my $Listline;
my @ems;

open (FILE,"<$Listfile");
while ($Listline=<FILE>) {
chop $Listline;
@ems = split(/$Delimiter/,$Listline);
if ($ems[1] eq "0") {
&built_tolist($ems[2]);
}
elsif ($ems[1] eq "1") {
push(@Tolist,$ems[4]);
}
else {
}
}
close(FILE);
return(1);
}


it comes 2 times (2 references in the called listfile) with the error:

readline() on closed filehandle FILE at G:/cgi-bin/mailing/send_2.pl
line 224.

I have used a local filehandle (*FILE)! Can sombody help me where to look?

Greetings...
Wijnand
 
W

Wijnand Nijs

Wijnand Nijs schreef:
Hello,

I have a problem with the next recursive subroutine used in a mailing
script:

#-----------------------
# sub built_tolist
# format lines listfiles:
# referense to a listfile = |0|nijs-bruls|
# subscribed address = |1|firstname|surname|mailaddress|etc.
# unsubscribed address = |2|firstname|surname|mailaddress|etc.
#-----------------------

sub built_tolist($) {
local (*FILE);
my $Listfile = shift;
my $Listline;
my @ems;

open (FILE,"<$Listfile");
while ($Listline=<FILE>) {
chop $Listline;
@ems = split(/$Delimiter/,$Listline);
if ($ems[1] eq "0") {
&built_tolist($ems[2]);
}
elsif ($ems[1] eq "1") {
push(@Tolist,$ems[4]);
}
else {
}
}
close(FILE);
return(1);
}


it comes 2 times (2 references in the called listfile) with the error:

readline() on closed filehandle FILE at G:/cgi-bin/mailing/send_2.pl
line 224.

I have used a local filehandle (*FILE)! Can sombody help me where to look?

Greetings...
Wijnand

Or is this the wrong group?
 
X

xhoster

Wijnand Nijs said:
Hello,

I have a problem with the next recursive subroutine used in a mailing
script:

#-----------------------
# sub built_tolist
# format lines listfiles:
# referense to a listfile = |0|nijs-bruls|
# subscribed address = |1|firstname|surname|mailaddress|etc.
# unsubscribed address = |2|firstname|surname|mailaddress|etc.
#-----------------------

sub built_tolist($) {
local (*FILE);

why not use lexical file handles?
my $Listfile = shift;
my $Listline;
my @ems;

open (FILE,"<$Listfile");

You are not checking whether the open succeeded or not. If the open
failed, you are still trying to read from the handle.

open (my FILE, "<$Listfile") or die "Can't open $Listfile, $!";

But why not use lexical file handles?

open (my $FILE, "<", $Listfile) or die $!;
it comes 2 times (2 references in the called listfile) with the error:

readline() on closed filehandle FILE at G:/cgi-bin/mailing/send_2.pl
line 224.

I have used a local filehandle (*FILE)!

Why? Are you coding for a very old Perl? Is this part of a homework
assignment with tortuous rules?

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
L

Leon Timmermans

Hello,

I have a problem with the next recursive subroutine used in a mailing
script:

#-----------------------
# sub built_tolist
# format lines listfiles:
# referense to a listfile = |0|nijs-bruls| # subscribed address =
|1|firstname|surname|mailaddress|etc. # unsubscribed address =
|2|firstname|surname|mailaddress|etc. #-----------------------

sub built_tolist($) {
local (*FILE);
my $Listfile = shift;
my $Listline;
my @ems;

open (FILE,"<$Listfile");
while ($Listline=<FILE>) {
chop $Listline;
@ems = split(/$Delimiter/,$Listline);
if ($ems[1] eq "0") {
&built_tolist($ems[2]);
}
elsif ($ems[1] eq "1") {
push(@Tolist,$ems[4]);
}
else {
}
}
close(FILE);
return(1);
}


it comes 2 times (2 references in the called listfile) with the error:

readline() on closed filehandle FILE at G:/cgi-bin/mailing/send_2.pl
line 224.

I have used a local filehandle (*FILE)! Can sombody help me where to
look?

Greetings...
Wijnand

Hi Wijnand,

There is a very easy solution to these kinds of problems: using lexical
filehandles. However, there are more issues with your code. First of
all, please always check the return value of open and close (and
best yet also check print). You probably don't want to use prototypes or
'&' sigils. Also, you seem to be storing the return value in a global
variable(@Tolist), which sounds like a bad idea to me. Also, chop may not
always do what you want it to do (imagine the last line of the file not
ending with a newline), you want to use chomp there. Also, quotes around
numbers aren't necessary.

To get back to your question, how about this one:

sub built_tolist {
my $Listfile = shift;

open my $file, '<', $Listfile;
while (my $Listline=<$file>) {
chop $Listline;
my @ems = split /$Delimiter/, $Listline;
if ($ems[1] eq 0) {
built_tolist($ems[2]);
}
elsif ($ems[1] eq 1) {
push @Tolist, $ems[4];
}
}
return 1;
}

Changing the semantics a little gives me this:

sub built_tolist {
my $Listfile = shift;
my @Tolist;

open my $file, '<', $Listfile or die "Could not open file $Listfile:
$!\n";
while (my $Listline=<$file>) {
chomp $Listline;
my @ems = split /$Delimiter/, $Listline;
if ($ems[1] eq 0) {
push @Tolist, built_tolist($ems[2]);
}
elsif ($ems[1] eq 1) {
push @Tolist, $ems[4];
}
}
return @Tolist;
}

It returns a list of values to mail, instead of storing it in a global
variable.

Regards,

Leon Timmermans
 
J

Joost Diepenmaat

Leon Timmermans said:
sub built_tolist($) {
local (*FILE);
my $Listfile = shift;
my $Listline;
my @ems;

open (FILE,"<$Listfile");
while ($Listline=<FILE>) {
chop $Listline;
@ems = split(/$Delimiter/,$Listline);
if ($ems[1] eq "0") {
&built_tolist($ems[2]);
}
elsif ($ems[1] eq "1") {
push(@Tolist,$ems[4]);
}
else {
}
}
close(FILE);
return(1);
}
...
There is a very easy solution to these kinds of problems: using lexical
filehandles.

I'm pretty sure using local() should work, if the open() call
succeeds. But you're right that lexical filehandles are probably a
better solution.

Regards,
Joost.
 
E

Eric Pozharski

Wijnand Nijs said:
I have used a local filehandle (*FILE)! Can sombody help me where to look?

Show your code. Works for me (despite it's awful)

22:26:56 113 [1:0]$ perl -wle '
sub zzz {
local *FILE;
open FILE, q|</etc/issue| or die $!;
warn q|fileno is |, fileno FILE;
print quotemeta <FILE>;
zzz(1) unless $_[0];
print quotemeta <FILE>;
close FILE; };
zzz();'
fileno is 3 at -e line 5.
Debian\ GNU\/Linux\ lenny\/sid\ \\n\ \\l\

fileno is 4 at -e line 5.
Debian\ GNU\/Linux\ lenny\/sid\ \\n\ \\l\

\

\

22:29:32 114 [1:0]$

Sorry for somewhat messy output (it's too late to look for two line
file).
 
W

Wijnand Nijs

(e-mail address removed) schreef:
why not use lexical file handles?


You are not checking whether the open succeeded or not. If the open
failed, you are still trying to read from the handle.

open (my FILE, "<$Listfile") or die "Can't open $Listfile, $!";

But why not use lexical file handles?

open (my $FILE, "<", $Listfile) or die $!;


Why? Are you coding for a very old Perl? Is this part of a homework
assignment with tortuous rules?

Xho

Ok, ok Xho... I am coding for a very old Perl because I am 57 years old
;) and try to make my server more interactive. So not a professional
programmer but a simple amateur, learning every day.

See also my respons to Leon.

Greetings...
Wijnand
 
W

Wijnand Nijs

Leon Timmermans schreef:
Hello,

I have a problem with the next recursive subroutine used in a mailing
script:

#-----------------------
# sub built_tolist
# format lines listfiles:
# referense to a listfile = |0|nijs-bruls| # subscribed address =
|1|firstname|surname|mailaddress|etc. # unsubscribed address =
|2|firstname|surname|mailaddress|etc. #-----------------------

sub built_tolist($) {
local (*FILE);
my $Listfile = shift;
my $Listline;
my @ems;

open (FILE,"<$Listfile");
while ($Listline=<FILE>) {
chop $Listline;
@ems = split(/$Delimiter/,$Listline);
if ($ems[1] eq "0") {
&built_tolist($ems[2]);
}
elsif ($ems[1] eq "1") {
push(@Tolist,$ems[4]);
}
else {
}
}
close(FILE);
return(1);
}


it comes 2 times (2 references in the called listfile) with the error:

readline() on closed filehandle FILE at G:/cgi-bin/mailing/send_2.pl
line 224.

I have used a local filehandle (*FILE)! Can sombody help me where to
look?

Greetings...
Wijnand

Hi Wijnand,

There is a very easy solution to these kinds of problems: using lexical
filehandles. However, there are more issues with your code. First of
all, please always check the return value of open and close (and
best yet also check print). You probably don't want to use prototypes or
'&' sigils. Also, you seem to be storing the return value in a global
variable(@Tolist), which sounds like a bad idea to me. Also, chop may not
always do what you want it to do (imagine the last line of the file not
ending with a newline), you want to use chomp there. Also, quotes around
numbers aren't necessary.

To get back to your question, how about this one:

sub built_tolist {
my $Listfile = shift;

open my $file, '<', $Listfile;
while (my $Listline=<$file>) {
chop $Listline;
my @ems = split /$Delimiter/, $Listline;
if ($ems[1] eq 0) {
built_tolist($ems[2]);
}
elsif ($ems[1] eq 1) {
push @Tolist, $ems[4];
}
}
return 1;
}

Changing the semantics a little gives me this:

sub built_tolist {
my $Listfile = shift;
my @Tolist;

open my $file, '<', $Listfile or die "Could not open file $Listfile:
$!\n";
while (my $Listline=<$file>) {
chomp $Listline;
my @ems = split /$Delimiter/, $Listline;
if ($ems[1] eq 0) {
push @Tolist, built_tolist($ems[2]);
}
elsif ($ems[1] eq 1) {
push @Tolist, $ems[4];
}
}
return @Tolist;
}

It returns a list of values to mail, instead of storing it in a global
variable.

Regards,

Leon Timmermans

Thanks Leon for the help. The most important thing I learned is to check
the return value when open and close files. That gived me the
information that the file was not there (path error, oeps...).

Now it works fine (also whith the old fashion "local (*FILE)").

Greetings...
Wijnand
 
B

Ben Morrow

Quoth "Peter J. Holzer said:
sub built_tolist($) { [...]
&built_tolist($ems[2]);
You probably don't want to use prototypes or '&' sigils.

And certainly not both together.

Well... about the only case where using & on a sub call is reasonable in
modern Perl is when you know the sub is prototyped, but specifically
want to avoid the prototyped behaviour. See e.g. Hash::Util::Fieldhash
for an example of where this can be useful.

Ben
 

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
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top