Flushing Perl STDIN buffer
Is there any way to clear the STDIN buffer in Perl? A part of my pr开发者_Go百科ogram has lengthy output (enough time for someone to enter a few characters) and after that output I ask for input, but if characters were entered during the output, they are "tacked on" to whatever is entered at the input part. Here is an example of my problem:
for(my $n = 0; $n < 70000; $n++){
print $n . "\n";
}
chomp(my $input = <STDIN>);
print $input . "\n";
The output would include any characters entered during the output from that for loop. How could I either disable STDIN or flush the STDIN buffer (or any other way to not allow extra characters to be inserted into STDIN before calling it)?
It looks like you can accomplish this with the Term::ReadKey
module:
#!perl
use strict;
use warnings;
use 5.010;
use Term::ReadKey;
say "I'm starting to sleep...";
ReadMode 2;
sleep(10);
ReadMode 3;
my $key;
while( defined( $key = ReadKey(-1) ) ) {}
ReadMode 0;
say "Enter something:";
chomp( my $input = <STDIN> );
say "You entered '$input'";
Here's what happens:
ReadMode 2
means "put the input mode into regular mode but turn off echo". This means that any keyboard banging that the user does while you're in your computationally-expensive code won't get echoed to the screen. It still gets entered intoSTDIN
's buffer though, so...ReadMode 3
turnsSTDIN
into cbreak mode, meaningSTDIN
kind of gets flushed after every keypress. That's why...while(defined($key = ReadKey(-1))) {}
happens. This is flushing out the characters that the user entered during the computationally-expensive code. Then...ReadMode 0
resetsSTDIN
, and you can read fromSTDIN
as if the user hadn't banged on the keyboard.
When I run this code and bang on the keyboard during the sleep(10)
, then enter some other text after the prompt, it only prints out the text I typed after the prompt appeared.
Strictly speaking the ReadMode 2
isn't needed, but I put it there so the screen doesn't get cluttered up with text when the user bangs on the keyboard.
I had the same problem and solved it by just discarding anything in STDIN after the processing like this:
for(my $n = 0; $n < 70000; $n++){
print $n . "\n";
}
my $foo=<STDIN>;
print "would you like to continue [y/n]: ";
chomp(my $input = <STDIN>);
print $input . "\n";
{ local $/; <STDIN> }
This temporarily - limited to scope of the block - sets $/, the input record seperator, to be undef, which tells perl to just read everything instead of reading a line at a time. Then reads everything available on STDIN and doesn't do anything with it, thus flushing the buffer.
After that, you can read STDIN as normal.
精彩评论