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

Well, I think thats what I mean..

I'm using Net::Telnet to communicate with some network devices and I wish to store the entire conversation between my script and the device in a database.

Net::Telnet permits this by either specifying a file to write the log to or by passing a filehandle to an already open file.

e.g:

$telnet->input_log("/tmp/filename.tmp");

$fh=new FileHandle;
$fh->open(">/tmp/filename.tmp");
$telnet->input_log($fh);

In order to save the log using this method I have to write the log to disk, then read it back into a variable, then write it to the db.

My question is, is there anyway of creating a filehandle, which doesn't write to a file, but buffers the data written to it, which I can retrieve at the end of the operation..

e.g:

my $log="";
my $fh=new VFileHandle;
$fh->open();
#do stuff
$log=$fh->close();
##write the $log var to the database.
I've tried using the FileHandle module but can't work out what file/device to open to make this work.

If I make the filehandle object without opening a file I get a 'writing to closed filehandle' error..

Any help appreciated !

Thanks,

James

Replies are listed 'Best First'.
Re: Virtual Filehandles..
by diotalevi (Canon) on Nov 18, 2004 at 20:34 UTC

    If you are using perl 5.8 you can create a filehandle to a plain scalar.

    open my $fh, ">:scalar:raw", \ my $stored_output or die "Couldn't open memory handle: $!"; print $fh "Hello world!"; print $stored_output;
      Cool !

      On Win32, I had to remove the ":raw" to make it work on perl, v5.8.3 built for MSWin32-x86-multi-thread.

      With ":raw", I got no output (More accurately, NULL output), and warnings produced:
      Use of uninitialized value in concatenation (.) or string at -e line 1.

          Earth first! (We'll rob the other planets later)

      Wow! thanks for the quick replies! That looks like a very cool way around things, however I'm on 5.6 and can't upgrade, is there another method ?
        Yes though it isn't as nice. Tie your filehandle you'll write to and trap the writes. It looks like someone already wrote a module for this: Tie::Handle::Scalar. I've never used the module.
        IO::Scalar should work with 5.6. It's implementation is not as complete as open(FILE, \$var), but it's often sufficient.
Re: Virtual Filehandles..
by simonm (Vicar) on Nov 18, 2004 at 21:36 UTC
Re: Virtual Filehandles..
by pg (Canon) on Nov 18, 2004 at 21:01 UTC

    Continue from diotalevi's reply, you can actually just open it as if you are opening a normal file:

    use warnings; use strict; my $str; open FILE, ">", \$str; print FILE "abcd\n"; print FILE "1234\n"; print $str;#the content is there before close close FILE; print $str; #the content is still there after close

    Update - Just to add a more complete example with Net::Telnet:

    You have to use your real host name, user name and password to make it work.

    use Net::Telnet; use warnings; use strict; my ($file, $str); open $file, ">", \$str; my $t = new Net::Telnet(timeout => 10, input_log => $file, Prompt => " +/\[AAUA1\]/"); $t->open("foo"); $t->login("me", "hi"); $t->cmd("pwd"); $t->cmd("whoami"); $t->close(); print "\$str content:\n"; print $str;
Re: Virtual Filehandles..
by tilly (Archbishop) on Nov 19, 2004 at 02:57 UTC
    Yet Another Way To Do It. Use IPC::Open2 to create filehandles writing to/from the command perl -e 'print <>'

    Usually that is overkill, but there are situations where you've got multiple filehandles where the tie emulations and equivalents will cause something to block but this will not. (The block would happen because you are trying to talk to a process that is trying to talk to you, and both wait forever for the other to listen...) Ironically you're most likely to run into these situations when you're already using IPC::Open2 or IPC::Open3.