Очистка буфера Perl STDIN

#perl #buffer #stdin #flush

#perl #буфер #stdin #очистка

Вопрос:

Есть ли какой-либо способ очистить буфер STDIN в Perl? Часть моей программы имеет длительный вывод (достаточно времени, чтобы кто-то ввел несколько символов), и после этого вывода я запрашиваю ввод, но если символы были введены во время вывода, они «привязываются» к тому, что вводится во входной части. Вот пример моей проблемы:

 for(my $n = 0; $n < 70000; $n  ){
   print $n . "n";
}
chomp(my $input = <STDIN>);
print $input . "n";
  

Выходные данные будут включать любые символы, введенные во время вывода из этого цикла for . Как я могу отключить STDIN или очистить буфер STDIN (или любым другим способом, чтобы не допускать вставки дополнительных символов в STDIN перед его вызовом)?

Комментарии:

1. Хорошо, я искал ответ на этот вопрос уже 3 дня (не каждый час каждого дня, но я бы сказал, по крайней мере, 3 или 4 часа в день) и еще не нашел ответа, на самом деле я спросил своих коллег, которые также знают и используют Perl, иони тоже не знают, поэтому я считаю, что я приложил больше усилий, чем вы подразумеваете, что я вложил, кроме того, есть ли у вас какие-либо идеи относительно того, как сделать то, что я прошу? Поскольку я уже просматривал вашу ссылку около 3 дней назад, я попытался реализовать эти функции таким образом, чтобы логически устранить эту проблему, и это не сработало.

2. use IO::Handle;STDIN->autoflush(1);

3. Спасибо за ваш ответ, но это не решило проблему, кроме того, я помню, что чтение autoflush и flush хороши только для вывода, таких как STDERR и STDOUT, а не для ввода. Когда я попробовал то, что вы предложили, я все равно получаю символы, которые я ввел во время вывода цикла for, плюс то, что я когда-либо вводил в STDIN.

4. @JackManey: Как правило, «очистка» применяется к выводу, а не к вводу.

Ответ №1:

Похоже, вы можете выполнить это с Term::ReadKey помощью модуля:

 #!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'";
  

Вот что происходит:

  • ReadMode 2 означает «перевести режим ввода в обычный режим, но отключить эхо». Это означает, что любое нажатие клавиатуры, которое пользователь выполняет, пока вы работаете с дорогостоящим в вычислительном отношении кодом, не будет отражено на экране. Однако он все равно вводится в STDIN буфер, так что…
  • ReadMode 3 переходит STDIN в режим cbreak, что означает STDIN , что после каждого нажатия клавиши происходит сброс. Вот почему…
  • while(defined($key = ReadKey(-1))) {} происходит. Это удаление символов, введенных пользователем во время дорогостоящего с точки зрения вычислений кода. Затем…
  • ReadMode 0 сбрасывается STDIN , и вы можете читать, STDIN как если бы пользователь не стучал по клавиатуре.

Когда я запускаю этот код и нажимаю на клавиатуру во время sleep(10) , а затем ввожу какой-либо другой текст после приглашения, он выводит только текст, который я ввел после появления приглашения.

Строго говоря ReadMode 2 , он не нужен, но я поместил его туда, чтобы экран не был загроможден текстом, когда пользователь нажимает на клавиатуру.

Ответ №2:

У меня была такая же проблема, и я решил ее, просто отбросив что-либо в STDIN после такой обработки:

 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";
  

Комментарии:

1. — только что понял, что это работает только в том случае, если во время обработки происходит возврат, в противном случае он будет приостановлен до тех пор, пока кто-нибудь не нажмет enter

Ответ №3:

 { local $/; <STDIN> }
  

Это временно — ограничено областью действия блока — устанавливает $/ , разделитель входных записей, в значение undef, что указывает perl просто читать все, а не читать строку за раз. Затем считывает все, что доступно в STDIN, и ничего с этим не делает, тем самым очищая буфер.

После этого вы можете читать STDIN как обычно.

Комментарии:

1. Это не сработает. <STDIN> Вызов блокируется до тех пор, пока не будет прочитана «запись». Но если $/ есть undef , конца записи быть не может, поэтому она будет блокироваться до тех пор, пока не будет достигнут EOF.