http://www.perlmonks.org?node_id=1000282

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

Hey, I've got some problems with a little program. I want to write into 2 files but the ouput-structure differs inside those two.

I use this code:
for ($i=1;$i<=$max;$i++){ $pwd = &randomPwd($nmbchars); select (DB); print qq("$dept$w$i","7 days","$pwd",,,,,,\n); close(DB); select (newDB); print qq("$dept$w$i"\t>\t"$pwd"\n); close(newDB); }

The loop just runs 1 time and then the program stops. It should run multiple times.

Is there a restriction in opening and closing files inside a loop?

Replies are listed 'Best First'.
Re: Opening and closing files in loop
by BrowserUk (Patriarch) on Oct 22, 2012 at 08:30 UTC
    Is there a restriction in opening and closing files inside a loop?

    You aren't opening the files within the loop.

    select only makes a particular, already open, filehandle the default for print.

    But you are closeing those handles on the first pass, and they never get re-opened.

    Two possibilities:

    1. Don't close the files, just select between then:
      for ($i=1;$i<=$max;$i++){ $pwd = &randomPwd($nmbchars); select (DB); print qq("$dept$w$i","7 days","$pwd",,,,,,\n); select (newDB); print qq("$dept$w$i"\t>\t"$pwd"\n); }
    2. Instead of selecting between them, supply the required file handle to the print statements:
      for ($i=1;$i<=$max;$i++){ $pwd = &randomPwd($nmbchars); print DB qq("$dept$w$i","7 days","$pwd",,,,,,\n); print newDB qq("$dept$w$i"\t>\t"$pwd"\n); }

    Personally, I prefer the latter option.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    RIP Neil Armstrong

      Thank you very much!!
Re: Opening and closing files in loop
by Corion (Patriarch) on Oct 22, 2012 at 08:33 UTC

    You don't show the value(s) of $i and $max, so maybe there is a simple reason why your loop only gets run once.

    Personally, I would change the coding style in two places to avoid nasty errors:

    First, I would not use the C-style for construct but iterate over a range. I'd also use a lexical $i to avoid clobbering the loop counter through side-effects:

    for my $i (1..$max) { ... };

    Second, I would avoid using select for choosing the active output handle and print to the filehandles directly:

    print DB qq("$dept$w$i, ..."\n); print newDB qq("$dept$w$i, ..."\n);

    While rewriting your code to the new idiom, I saw that you seem to be running without warnings. As soon as you add use warnings; to the top of your script, or add -w to the Perl invocation, Perl will tell you what is going wrong.

Re: Opening and closing files in loop
by kcott (Archbishop) on Oct 22, 2012 at 08:49 UTC

    G'day lt007,

    Welcome to the monastery.

    Rather than continually changing the default filehandle with select, I'd use print with the required filehandle (e.g. print $fh qq{...}). Using this method, you only need to open the files once before the loop and close them once after the loop.

    Your question title (Opening and closing files in loop) suggests you're maybe confused between select and open. You don't use open in your loop nor show any code where it is used.

    You don't show how $max gets its value. This variable controls how many times the loop is entered. Try print "$max\n"; just before the loop to test this.

    Did you intend to put an ampersand in front of randomPwd($nmbchars)? See perlsub for what it does and whether you need it (normally you don't).

    -- Ken