Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Non-blocking read

by tomazos (Deacon)
on Nov 12, 2001 at 22:28 UTC ( #124876=perlquestion: print w/replies, xml ) Need Help??

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

How do you perform a non-blocking read from standard input?

I want to write an interactive script that I am going to run from a command-line.

I want it to do things and read input keystrokes that may be present at the same time.

To do this, I believe the best way would be to setup a tight loop that alternated between testing if there are any characters on the input and going on with it's tasks at the same time.

In order to do that I would need a call (similar to the flock non-blocking flag) that would tell me if new input is present yet and return immediately if it is not.

Any ideas?

Replies are listed 'Best First'.
Re: Non-blocking read
by wog (Curate) on Nov 12, 2001 at 23:11 UTC
    Probably the easiest, and most portable (since, apparently, Windows perl only supports select for sockets, not to mention that it probably doesn't support termios.), way to do this would be to use Term::ReadKey:

    use Term::ReadKey; for (;;) { if (defined(my $c = ReadKey(-1))) { # got a character $c, process } # do other stuff }
Re: Non-blocking read
by kwoff (Friar) on Nov 12, 2001 at 22:43 UTC
    Use select. Example in the while loop below:
    #!/usr/local/bin/perl -w use strict; BEGIN { # from Camel book 2nd ed. p.474 use POSIX qw(:termios_h); my ($term, $oterm, $echo, $noecho, $fd_stdin); $fd_stdin = fileno(STDIN); $term = POSIX::Termios->new(); $term->getattr($fd_stdin); $oterm = $term->getlflag(); $echo = ECHO | ECHOK | ICANON; $noecho = $oterm & ~$echo; sub cbreak { $term->setlflag($noecho); $term->setcc(VTIME, 1); $term->setattr($fd_stdin, TCSANOW); } sub cooked { $term->setlflag($oterm); $term->setcc(VTIME, 0); $term->setattr($fd_stdin, TCSANOW); } } END { cooked(); } cbreak(); while (1) { my ($rin, $rout, $nfound); $rin = ''; vec($rin, fileno(STDIN), 1) = 1; if ($nfound = select($rout=$rin, undef, undef, 0.001)) { my ($key); sysread(STDIN, $key, 1); if ($key eq 'j') { print "It was j!\n"; } elsif ($key eq 'q') { print "I'm melting!\n"; exit; } } }
Re: Non-blocking read
by Anonymous Monk on Nov 13, 2001 at 19:29 UTC
    If you're on a Unix like system you can user termios to set a timeout. Will a timeout do what you want?

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://124876]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2023-02-02 18:24 GMT
Find Nodes?
    Voting Booth?
    I prefer not to run the latest version of Perl because:

    Results (20 votes). Check out past polls.