in reply to Writing to file with filehandler in variable, scope issue, clobber becomes append

Hello Marcool,

it would seem that print is appending rather than clobbering.

That’s what print does! The only clobbering in your code occurs when the file is opened for writing: if “file.txt” already exists, its contents will be clobbered by the open($fh, '>', "file.txt") command. But when you print, the file pointer is moved to the position in the file immediately following the last character printed; so the next print begins there. Why did you expect it to work otherwise?

BTW, it’s usual for a script to return 0 to indicate success and non-zero to indicate failure. Also, it would be better to put the contents of sub mysub into an END block — see BEGIN, UNITCHECK, CHECK, INIT and END.

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: Writing to file with filehandler in variable, scope issue, clobber becomes append
by Marcool (Acolyte) on Apr 13, 2016 at 14:37 UTC

    Oh I never realized that's the way print works! I guess that I though it somehow "passed" its information to the filehander, which dealt with it depending on the "instruction" in the open statement.
    So if I want to clobber the file, I have to use open every time the loop loops do I? Or can I tell print to start from the top of the file somehow? Or empty the file using something other than open() again?

    Thank you for the tip on the exit codes. I suppose I didn't pay too much attention when entering them...
    Also the END issue with the sub. Does that have to do with performance? As in the sub will only be interpreted after everything else, or is there another reason?

      You can tell it to print from the top of the file via the seek command:

      seek $fh, 0, 0;

      But that won’t clobber the file contents; if the text you print is shorter than the text you are overprinting, the original text will still show up at the end of your newly-printed text. If you really need to erase the file contents before printing, then yes, you can close the filehandle and then re-open it for writing.

      Using END isn’t a matter of performance, it’s a means of simplifying and ensuring correctness. It’s simpler, because you don’t have to explicitly call the sub at each exit point in your code; the cleanup code gets called automatically. And suppose you add a third, then a fourth, then a fifth exit point, and somewhere in all that you forget to call the cleanup sub? That’s the sort of bug that can be hard to detect. Better to ensure correctness via code structure than by relying on human memory!

      BTW, I should have said that in Perl the preferred way to exit a script abnormally (i.e., indicating failure of some kind) is to throw an exception using die:

      open(my $fh, '>', 'file.txt') or die "Cannot open file.txt for writing +.\n";

      If the exception isn’t caught, the script will exit, but any END blocks will still be run first.

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Opening in '>' mode will clobber, of course, but opening inside of a tight loop can be inefficient. Another solution could be to truncate to 0, and then seek to 0 before printing again. But I have no idea if that's actually less inefficient.


      Dave

Re^2: Writing to file with filehandler in variable, scope issue, clobber becomes append
by Marcool (Acolyte) on Apr 13, 2016 at 18:07 UTC

    Ok, I've edited to close and open the filehandler each time the loop loops (I agree, seems kind of inefficient, that's why I kept it out of the loop at first). Maybe I'll compare that with the truncate and seek option at some point, but for now it's good enough.

    I also get what you mean by using the "END" block. I never knew of it's existence and it does indeed do exactly what I want to do with my cleanup sub. Thanks for that.

    The reason I had quit using die was precisely so I could call my sub. But now I have the END construct I have changed all the "unless..."s back to "or die..."s.

    I'm not sure I would ever have figured out what I had not understood properly without your help. Even the page for "print" on perldoc doesn't really explain this...

    You've been a great help! Thanks again.

    All the best, Mark.