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

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

I have rescently been attempting to use IO::String to keep format output, however I am having a few problems. Am I just using it wrong? Information as to how I got to this point can be found here.


use IO::String; use strict; my $io = tie(*TEST,'IO::String'); my $temp = $io->string_ref; my $t1 = '1'; my $t2 = '2'; my $t3 = '3'; select(TEST); write(); format TEST= @||| @||| @||| $t1,$t2,$t3 . select(STDOUT); print $$temp;


When Executed, this is what happens:
perl -w test.pl write() on unopened filehandle TEST at test.pl line 14.


Thanks



"Weird things happen, get used to it."

Flame ~ Lead Programmer: GMS

Replies are listed 'Best First'.
Re: format and IO::String
by jmcnamara (Monsignor) on Jan 29, 2002 at 16:23 UTC

    As runrig and simon.proctor pointed out in the last node the best way to get formatted text into a variable is to use formline and the accumulator $^A.

    Also, as runrig pointed out write won't work directly with IO::Scalar.

    The following is a example of putting formatted text into a variable. If you really need it in a IO::Scalar you can transfer it on from there.

    #!/usr/bin/perl -w use strict; my $temp; my $format = '@||| @||| @|||'; my $t1 = '1'; my $t2 = '2'; my $t3 = '3'; # Create the format formline($format, $t1, $t2, $t3); $temp = $^A; # Store the accumulator $^A = ''; # Clear the accumulator print $temp;

    --
    John.

      I'd really prefer to be able to use a format declaration, because the formats I'll need to use are usually multiline and I don't want to have to go into all that complicated stuff when I decided to use format to simplify things to begin with.

      I've been experementing with pipe, but it keeps locking up... Any suggestions?

      This code seems to work:
      pipe(TESTOUT,TEST) or die($!); my $t1 = '1'; my $t2 = '2'; my $t3 = '3'; select(TEST); $|=1; print "Testing..."; write(); close(TEST); select(STDOUT); my @temp = <TESTOUT>; print join('',@temp); format TEST= @||| @||| @||| $t1,$t2,$t3 @||| @||| @||| $t3,$t2,$t1 .


      However, when I try a longer format, it tends to freeze:

      my $GMS = new GMS; my $sitename = $GMS->getsetting('GUILD','SITENAMET'); my($name,$email,$icq) = ('Iron','flame@berkshire.rr.com','16307443'); my @stats = (100,100,25); my $skills = [ {'SKILL' => 'Anatomy','VALUE' => 100}, {'SKILL' => 'Swordsmanship','VALUE' => 100}, {'SKILL' => 'Tactics','VALUE' => 100} ]; my $notes = "This is a long test string.\n\n" x 10; pipe(GMMAILO,GMMAIL) or die($!); select(GMMAIL); $|=1; print "Testing..."; write();# or die($!); close(GMMAIL); select(STDOUT); my @temp = <GMMAILO>; print join('',@temp);




      "Weird things happen, get used to it."

      Flame ~ Lead Programmer: GMS

Re: format and IO::String
by jmcnamara (Monsignor) on Jan 31, 2002 at 16:18 UTC

    Okay. I can see what you are getting at now.

    Here is a possible solution based on your pipe code. It uses an anonymous temporary file to store the formatted string:

    #!/usr/bin/perl -w use strict; use IO::File; print "Testing...\n"; my $t1 = '1'; my $t2 = '2'; my $t3 = '3'; my $fh = IO::File->new_tmpfile() or die $!; $fh->format_name("TEST"); select($fh); write(); seek($fh, 0, 0); # Rewind the file my $str = do {local $/; <$fh>}; select(STDOUT); print $str; format TEST= @||| @||| @||| $t1,$t2,$t3 @||| @||| @||| $t3,$t2,$t1 . __END__ Output: Testing... 1 2 3 3 2 1

    --
    John.

      Hmm, It works, I'll give you that. I'm still confused as to why it locks up on my version though. Take a look at this code (I was experementing and benchmarking at the same time):

      #!/usr/bin/perl -w use strict; use IO::File; use GMS; require "GMSConstant.pl"; use Benchmark qw(cmpthese); my $t1 = '1'; my $t2 = '2'; my $t3 = '3'; my $GMS = new GMS; my $sitename = $GMS->getsetting('GUILD','SITENAMET'); my($name,$email,$icq) = ('Iron','flame@berkshire.rr.com','16307443'); my @stats = (100,100,25); my $skills = [ {'SKILL' => 'Anatomy','VALUE' => 100}, {'SKILL' => 'Swordsmanship','VALUE' => 100}, {'SKILL' => 'Tactics','VALUE' => 100} ]; my $onotes = "This is a long test string.\n\n" x 30; my $notes; sub otherway{ $notes = $onotes; #Re-Initialize variable since it was wiped out by + the write() my $fh = IO::File->new_tmpfile() or die $!; $fh->format_name('GMMAIL'); #This one works regardless of which format it's attached to. select($fh); write(); seek($fh, 0, 0); # Rewind the file my $str = do {local $/; <$fh>}; select(STDOUT); print $str; } sub myway{ $notes = $onotes; #Re-Initialize variable since it was wiped out by + the write() pipe(TESTOUT,TEST) or die($!); select(TEST); $~='GMMAIL'; #Note THIS Line: When set to 'TEST' everything's fine... #however, when set to GMMAIL like this, it locks up. #What's the difference that causes it to work for one but #not the other? $|=1; write(); close(TEST); select(STDOUT); my @temp = <TESTOUT>; print join('',@temp); close(TESTOUT); } cmpthese(10000,{ 'Suggestion' => \&otherway, 'MyTest' => \&myway} ); format TEST= @||| @||| @||| $t1,$t2,$t3 @||| @||| @||| $t3,$t2,$t1 . format GMMAIL= @||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +||||||||| "$sitename - Application" Name: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | Notes: ^<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $name, $notes E-Mail: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $email, $notes ICQ: @<<<<<<<<<< | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $icq, $notes ---------------------------------------| ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes /------\ | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes | Stats | | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes |--------| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes |@<<: @>>| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $GMS::Constant::STATS[0],$stats[0], $notes |@<<: @>>| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $GMS::Constant::STATS[1],$stats[1], $notes |@<<: @>>| | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $GMS::Constant::STATS[2],$stats[2], $notes \------/ | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes ---------------------------------------| ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes Skills | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes ------ | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes @<<<<<<<<<<<<<: @###.# | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $skills->[0]->{'SKILL'},$skills->[0]->{'VALUE'}, $notes @<<<<<<<<<<<<<: @###.# | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $skills->[1]->{'SKILL'},$skills->[1]->{'VALUE'}, $notes @<<<<<<<<<<<<<: @###.# | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $skills->[2]->{'SKILL'},$skills->[2]->{'VALUE'}, $notes ~~ | ^<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<< $notes @>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +>>>>>>>>> $GMS->getsetting('FILE','CGIBINS').'/join.c +gi?admin' .


      The comments inside the tested subs should explain my current question well enough.

      FYI: It appears that when it actually works, my way is faster by about 3%. But I suppose regardless of what's faster, I have to use what works... heh.

      Thanks for the suggestion.



      "Weird things happen, get used to it."

      Flame ~ Lead Programmer: GMS

Re: format and IO::String
by dws (Chancellor) on Feb 01, 2002 at 02:29 UTC
    I admire your perseverance, though there comes a time when it's time to fall back on plan B. Were it me, my Plan B would involve sprintf with a helper function to center strings.
    It's not the Zen way, but it gets the job done.
    -- Garrison Keillor
      Unfortunately, if you look at the longer format (the one I'm really trying to use) it's a little more complex than sprintf() could easily handle. I'm doing more than just centering after all.



      "Weird things happen, get used to it."

      Flame ~ Lead Programmer: GMS

Re: format and IO::String
by simon.proctor (Vicar) on Jan 29, 2002 at 04:04 UTC
    Update I was repeating myself from this node. Sorry.