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

I need to write a script that does this:

1. Reads input from a database into a file
2. Accepts input from user
3. Writes input to a file
4. Accepts more input.

Here is an example.
@colors = qw(pink yellow blue green); open(COLORS, ">>colors.txt"); foreach $color (@colors){ print COLORS "$color\n"; print "sending $color to File\n"; } close(COLORS); while (<STDIN>){ chomp; print COLORS $_; if ($_ eq "quit"){exit} }
The problem lies when the program is getting input from the user. If for some reason the program ends improperly all the input the user has entered will just dissappear.

Maybe I'm missing something very simple. But how can I write directly to the file after each input, without having to open and close the file each time?

Replies are listed 'Best First'.
Re: how do I write directly to a file
by davorg (Chancellor) on Jun 07, 2001 at 17:26 UTC

    You're printing to a file after you've closed it. Using -w in your script would have caught this problem.

    Also, you need to check the return value from open like this:

    open(COLORS, ">>colors.txt") || die "Can't open colors.txt: $!\n";
Re: how do I write directly to a file
by mugwumpjism (Hermit) on Jun 07, 2001 at 19:31 UTC

    Perl uses buffering on its filehandles; data is cached and written in 4K chunks. To turn that off, set the file handle to auto flush;

    use IO::Socket; @colors = qw(pink yellow blue green); open(COLORS, ">>colors.txt") or die $!; # turn off stdio buffering on COLORS COLORS->autoflush(1); foreach $color (@colors){ print COLORS "$color\n"; print "sending $color to File\n"; } while (<STDIN>) { chomp; exit if ($_ eq "quit"); print COLORS $_; }

      The other way to turn off buffering is to set the $| variable to a true value. This effects the currently selected default output filehandle (generally STDOUT) but you can change it on other filehandles like this:

      my $fh = select COLORS; $|++; select $fh;

      or in slightly more scarey code, like this:

      select((select(COLORS), $| = 1)[0]);

      So you can see why the IO::Socket method is preferred :)

      --
      <http://www.dave.org.uk>

      Perl Training in the UK <http://www.iterative-software.com>

Re: how do I write directly to a file
by azatoth (Curate) on Jun 07, 2001 at 17:18 UTC
    open (FH, ">> myfile.txt"); print FH; # whatever you want, whenever you want, using this command
Re: how do I write directly to a file
by bwana147 (Pilgrim) on Jun 07, 2001 at 19:42 UTC

    First, you close COLOR just after writing the default values from @colors. You should close it after the second while loop.

    Second, if you want to force your data to be written at once, you need to set the autoflush, by means of the $| variable. As $| acts on STDOUT by default, you need to select your COLORS before, and select STDOUT back:

    select +(select(COLORS),$| = 1)[0];

    --bwana147