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

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question: (strings)

I want to be able to play with a string as if it were a I/O stream. You can see this sort of functionality in C++ with sstream, and in Java with StringBuffer*Stream. A simple e.g., I'd love to be able to do something like:
my $stringfile = FileHandle::newFromString( "One fish\nTwo fish\nThree + fish\nFour fish" ); while( <$stringfile> ) { dosomething( $_ ); }
...but on a larger scale. Cheers, - jsproat

Originally posted as a Categorized Question.

Replies are listed 'Best First'.
Re: How do I treat a string like a filehandle?
by davido (Cardinal) on Oct 02, 2003 at 03:55 UTC
    You may open a file handle to "in memory" files (ie, scalars... or strings), if you're using a new enough version of Perl. I believe this feature was introduced with 5.8.0.

    Per perlfunc:open; 'File handles can be opened to "in memory" files held in Perl scalars via:
    open( $fh, '>', \$variable) || die ....
    Though if you try to re-open STDOUT or STDERR as an "in memory" file, you have to close it first.'

    Another example provided in the POD is:

    open(MEMORY, '>', \$var) or die "Can't open memory file: $!\n"; print MEMORY "foo!\n";

Re: How do I treat a string like a filehandle?
by runrig (Abbot) on Sep 16, 2000 at 00:27 UTC
      I mean the IO::Scalar module from the IO-Stringy distribution on CPAN :)
        Thanks! :-,
Re: How do I treat a string like a filehandle?
by hsinclai (Deacon) on Mar 09, 2004 at 04:14 UTC
    Just did this in a real app - nearly fell out of the chair when it worked.
    require 5.8.0; ## in order to write NSANS format to a scalar use strict; foreach $ns_answer (@ns_answer) { open(NSANS,">", \$ns_holder) or die("bla..\n"); write NSANS; print OFILE $ns_holder; close(NSANS); } format OFILE= ## for the disk file report @<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<< $adr, $ptr_answer . format NSANS= ## written to handle, then to scalar, then printed t +o OFILE @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<< $ns_answer .
    To clarify, the format NSANS was defined, but when used, the scalar $ns_holder is opened to write to. Once the write is done, the scalar $ns_holder contains the NSANS-formatted structure.

    Then the scalar $ns_holder can be written ("print"ed) to another handle, in this case the format OFILE (the final output file).. so a format(ed) thing containing different scalars can get written to a previously defined and already open'ed file handle (two identical output formats, containing different scalars, written to a single output file handle).

    That wasn't too clear - sorry - but I hope it's evident that you can write to a handle to a scalar.
      And if you are using a pre-5.80 level, or just want to be backward compatible, you can use IO::Scalar
      #!/usr/bin/perl #You could use IO::Scalar which seems to #be part of IO::Stringy. use IO::Scalar; $data = "My message:\n"; ### Open a handle on a string, and append to it: $SH = new IO::Scalar \$data; print $SH "Hello"; print $SH ", world!\nBye now!\n"; print "The string is now: ", $data, "\n"; ### Open a handle on a string, read it line-by-line, then close it: $SH = new IO::Scalar \$data; while (<$SH>) { print "Got line: $_"; } close $SH;

      I'm not really a human, but I play one on earth. flash japh
Re: How do I treat a string like a filehandle?
by indigo (Scribe) on Sep 16, 2000 at 03:59 UTC
    Use a pipe:
    #!/usr/bin/perl -w use FileHandle; use strict; my $string =<<EOD; One fish Two fish Red fish Blue fish EOD my $fh = new FileHandle("echo \'$string\' |") or die; print $_ while <$fh>;
      No point in invoking a shell there, when this will do:
      my $fh = FileHandle->new or die "Cannot create filehandle: $!"; defined(my $pid = open($fh, "-|")) or die "Cannot fork: $!"; unless ($pid) { print <<'EOD'; One fish Two fish Red fish Blue fish EOD exit 0; } print $_ while <$fh>; # in parent
      But again, this forks (as does yours), and it's much better to use IO::Stringy to do it all within one process.

      -- Randal L. Schwartz, Perl hacker

Re: How do I treat a string like a filehandle?
by sproaticus (Initiate) on Sep 16, 2000 at 00:29 UTC
    Sorry, newbieitis. Now I'm logged in, and have a more readable version of the code from my question:
    my $stringfile = FileHandle::newFromString( "One fish\nTwo fish\nThree + fish\nFour fish" ); while( <$stringfile> ) { dosomething( $_ ); }
    Cheers, - jsproat

    Originally posted as a Categorized Answer.