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

Can anyone please tell me why I get a readline() on unopened filehandle message.
foreach (@files) { my $FH = $_; open (FILE, "<$FH"); OUTER: while ((my $line_B = <FILE>)) { last OUTER unless defined($line_B = <$FH>); ## The message applie +s to this line my $batch; do { $batch .= $line_B; } until ($line_B =~ m/^\s*go\s*$/i); $dbh->do($batch) if ($line_B =~ m/^\s*go\s*$/i); } }

Replies are listed 'Best First'.
Re: readline() on unopened filehandle
by Skeeve (Parson) on Oct 07, 2005 at 11:42 UTC
    Because $FH isn't the filehandle, but FILE is
    last OUTER unless defined($line_B = <FILE>); # this should do

    $\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
Re: readline() on unopened filehandle
by Perl Mouse (Chaplain) on Oct 07, 2005 at 11:44 UTC
    Because $FH isn't a file handle - FILE is.

    But beside that, you have more problems. You're not checking the return value of 'open', the file might not open. Furthermove, if you do:

    while ((my $line_B = <FILE>)) { last OUTER unless defined ($line_B = <FILE>)
    you will be skipping every odd line.
    Perl --((8:>*
      Why would I be skipping every odd line?
        Because you read a line in the while, and then discard that line, and read the next line in your unless statement.
        Perl --((8:>*
        A reply falls below the community's threshold of quality. You may see it by logging in.
Re: readline() on unopened filehandle
by Zaxo (Archbishop) on Oct 07, 2005 at 11:46 UTC

    In line 10, the one you note, $FH is the file name, not a handle. I'm not sure you want that line at all, since you just read a line to the same variable in the while condition. I suspect you're trying to detect eof there, but you'll also clobber your loop variable and skip every other line of the file.

    I think you need to review your code carefully. I'm not sure what you're trying to do, but I'm certain that this won't do it. Your do {} until //; loop keeps tacking the same text onto $batch until it matches something that that it never will if it didn't the first time round. You'll loop endlessly and $batch will grow until you run out of memory.

    Update: If you are trying to detect eof to skip the last line, this works,

    while (<$fh>) { last if eof; print; }

    After Compline,
    Zaxo

Re: readline() on unopened filehandle
by blazar (Canon) on Oct 07, 2005 at 11:51 UTC
    I think you may want to read up on eof. In any case that last wouldn't do anything useful in any case: despite the name of your label, it seems to me that at all effects you're not leaving an outer loop, and you're already iterating over a file. You're also missing a line every two. Do you really want to?

    To answer your question, anyway, on the last line of your input file the file itself gets closed, so you can operate on that $line, but you can't read further lines. What did you expect to do?!? Update: ignore this, I didn't notice your typo. Right answer e.g. at Skeeve's reply.

Re: readline() on unopened filehandle
by radiantmatrix (Parson) on Oct 07, 2005 at 16:03 UTC

    Compare and contrast:

    # use this form of foreach instead of 'my $FH = $_' foreach my $FH (@files) { # use 3-arg form of open() for safety, and deal with # being unable to open the file. open my $FILE, '<', $FH or die("Cannot read $FH: $!"); # deal with each line of the file. while loop exits # when EOF is reached. my $batch; OUTER: while (<FILE>) { $batch .= $_; # cat this line to $batch # if we just read a line that's 'GO', run the batch and # reset the variable $batch to be empty if (m/^\s*go\s*$/i) { $dbh->do($batch); # you should check for and deal with DBI errors here $batch = ''; } } # if we didn't reach a 'GO', there will be stuff in $batch, so # we should report that fact. warn "File '$FH' contained unexecuted commands:\n$batch\n"; }

    Once you get that down, it becomes much easier to explore other algorithms, like this one:

    foreach my $FH (@files) { open my $FILE, '<', $FH or die("Cannot read $FH: $!"); my $data = join('', <$FILE>); # slurp file! # split on lines containing only 'GO' (and optionally, whitespace) foreach my $batch ( split /\n\s*go\s*\n/i, $data ) { # if you need the 'go', you'll need to do $batch.="\nGO"; here $dbh->do($batch); # error handling here } }
    <-radiant.matrix->
    A collection of thoughts and links from the minds of geeks
    The Code that can be seen is not the true Code
    "In any sufficiently large group of people, most are idiots" - Kaa's Law
Re: readline() on unopened filehandle
by Anonymous Monk on Oct 07, 2005 at 12:05 UTC
    You're still not checking open for failure, why?
      Because I very rarely program in Perl.

        No mater what the language you should always check the return value from system and library calls.