Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: Pre-empting STDIN during Testing

by Revelation (Deacon)
on Feb 15, 2005 at 01:38 UTC ( [id://431004]=note: print w/replies, xml ) Need Help??


in reply to Pre-empting STDIN during Testing

The easiest way to do this is to use IO::Handle:
#!/usr/bin/perl use strict; use warnings; use IO::Handle; open (INPUT, "myfile") || die $!; if (my $fh = STDIN->fdopen(\*INPUT, "r")) { print <>; $fh->close; } close INPUT;
You'll notice that this (at the least) solves your problem with the diamond operator. With regards to a  while (<>) loop, for which I assume, you have a  last() somewhere, the solution is not as clear. Obviously, any file has a limited length. Perhaps, there's some way to use IO::Handle as a base and generate some sort of callback routine that could generate more data, but that's a little too dirty for me. Realistically, are you going to need more than, say, 2,000 lines? If not, then just create a 2,000 line file.

What's nice about this approach is that IO::Handle handles reverting STDIN to its previous state, after  $fh->close for you. Moreover, it's also a rather simple approach. However, in addition, you could also always localize STDIN, like so:
{ local *STDIN; open(STDIN,'myfile'); #local *STDIN = *MYFILE; print <>; close(STDIN); }
Both of these aproaches will work whether you're calling STDIN in a used module or in the test script, itself. However, I assume each approach has different limitations as to backwards compatibility which I have not explored as of yet.

P.S: FYI, this is technique is generally called 'overloading STDIN'. Your searches would have been more successful, even on perlmonks, if you had used the proper vocabulary. :)

Update: With regards to your specific question, here's a possible (untested--closer to pseudocode) solution, which mimics your own (in functionality.)
my @lines = ( 'a string with numbers and letters 4678', '5678', '46789', ' 4678', '4678', ); open (INPUT, '+<', "tmpfile") || die $!; print INPUT $_."\n" for @lines; seek(INPUT,0,0); if (my $fh = STDIN->fdopen(\*INPUT, "r")) { my $room = enter_number(); $fh->close; print "Room: $room\n"; } close INPUT; unlink 'tmpfile';
Moreover, and the true beauty of IO::Handle, is that you can inherit from it. If you want to have a retrieve values from a list, rather than using my silly workaround, then feel free to write a module inheriting from IO::Handle that does so (my advice would be to overload perhaps fdopen and definitely getline and getlines)! Otherwise, IO::Handle _at least_ gives you a template for extending Perl's IO system in a more flexible manner than tying a hash. Perhaps, another monk will have an in-the-box workaround on IO::Handle to allow you to use a callback to a subroutine that shifts from an array (look at IO::String to see how this is handled for strings--you could modify that), but until then, you now have a pretty flexible solution that only involves a temporary file (which can be created using IO::File); I'm going to sleep now, but perhaps tomorrow, I'll think of a better solution, or somebody smarter than myself, like merlyn will do so.

Gyan Kapur
The Worst Nodes Upvoter!

Replies are listed 'Best First'.
Re^2: Pre-empting STDIN during Testing
by jkeenan1 (Deacon) on Feb 15, 2005 at 02:34 UTC
    Revelation wrote: P.S: FYI, this is technique is generally called 'overloading STDIN'. Your searches would have been more successful, even on perlmonks, if you had used the proper vocabulary. :)

    Really? What makes you think that?

    I took your suggestion and did a Google Groups search for the exact phrase "overloading STDIN." Nothing on c.l.p.misc, c.l.p.modules or perl.qa.

    I then Super Searched the monastery archives for that phrase. Had to hit the button at least 5 times. Had to go back to an April 29 2001 posting by chromatic (who else?) , Re: Problem with tie *STDIN, 'IO::Scalar', \$text;, to find a node that had contained both words (albeit separated from each other) and had some relevance.

    Now, if I wanted to overcome the problem with the diamond operator, I would certainly have thought in terms of overloading, because operators are what one overloads. And in the node cited above, chromatic does speak of "overloading TIEHANDLE." But I don't think "overloading STDIN" is a phrase that people have commonly used.

      Calm down, man. I wasn't trying to insult you or anything, just giving you a hint at a resource, which comes up if you search overloading STDIN: how do i redirect STDOUT, STDIN, or STDERR to a FILE? . There's something else that comes up on google, I believe, but legal issues prevent me from posting it.
Re^2: Pre-empting STDIN during Testing
by jkeenan1 (Deacon) on Feb 15, 2005 at 03:30 UTC
    I looked through the documentation for IO::Handle, IO::File, IO::Scalar, etc. while working on this ... and I confess I can't see the connection to my problem.

    Both of your code examples refer to opening files. I don't see the connection to reading from STDIN. How, for example, would you rework my code samples with IO::Handle or the localization of STDIN?

    Thanks for looking at this problem.

    Jim Keenan

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://431004]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (7)
As of 2024-04-18 17:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found