How to Check If Stdin Has Some Data

How do I check if stdin has some data?

On Unix systems you can do the following:

import sys
import select

if select.select([sys.stdin, ], [], [], 0.0)[0]:
print("Have data!")
else:
print("No data")

On Windows the select module may only be used with sockets though so you'd need to use an alternative mechanism.

How to determine if stdin is empty

It sounds like you want to run your program based on arguments either provided on the command line or piped into it from a file. If so, you should check whether the arguments have been provided on the command line first:

if (argc > 1) {
//parse argv
}

Then, check whether stdin is empty, and if not read the arguments in from stdin:

else if ((fseek(stdin, 0, SEEK_END), ftell(stdin)) > 0)
{
rewind(stdin);
char buffer[1024];
fgets(buffer, 1024 , stdin);
//parse args read in from stdin
}
else
{
//no redirection
}

Determine if Stdin has data with Go

os.Stdin is like any other "file", so you can check it's size:

package main

import (
"fmt"
"os"
)

func main() {
file := os.Stdin
fi, err := file.Stat()
if err != nil {
fmt.Println("file.Stat()", err)
}
size := fi.Size()
if size > 0 {
fmt.Printf("%v bytes available in Stdin\n", size)
} else {
fmt.Println("Stdin is empty")
}
}

I built this as a "pipe" executable, here is how it works:

$ ./pipe
Stdin is empty
$ echo test | ./pipe
5 bytes available in Stdin

Checking the stdin buffer if it's empty

There are several soutions:

poll or select with timeout of 0 - these would return immediately and result is either -1 with errno EAGAIN if no data available or number of descriptors with data (one, since you're checking only stdin).

ioctl is a swiss army knife of using descriptors. The request you need is I_NREAD:

if (ioctl(0, I_NREAD, &n) == 0 && n > 0)
// we have exactly n bytes to read

However the correct solution is to read everything you got (using scanf) as a line, then process the result - and this works good enough with sscanf:

char buf[80]; // large enough
scanf("%79s", buf); // read everything we have in stdin
if (sscanf(buf, "%d", &number) == 1)
// we have a number

... as long as you properly handle re-reading, strings that are longer than your buffer, and other real-life complications.

Test if stdin has input for C++ (windows and/or linux)

Here's a solution for POSIX (Linux): I'm not sure what's the equivalent of poll() on Windows. On Unix, The file descriptor with number 0 is the standard input.

#include <stdio.h>
#include <sys/poll.h>

int main(void)
{
struct pollfd fds;
int ret;
fds.fd = 0; /* this is STDIN */
fds.events = POLLIN;
ret = poll(&fds, 1, 0);
if(ret == 1)
printf("Yep\n");
else if(ret == 0)
printf("No\n");
else
printf("Error\n");
return 0;
}

Testing:

$ ./stdin
No
$ echo "foo" | ./stdin
Yep

Perl6: check if STDIN has data

You are using an old version of Perl 6, as v6.b is from before the official release of the language.

So some of what I have below may need a newer version to work.

Also why are you using sleep-until now+2 instead of sleep 2?


One way to do this is to turn the .lines into a Channel, then you can use .poll.

#!/usr/bin/env perl6
use v6.c;

sub MAIN () {
# convert it into a Channel so we can poll it
my $lines = $*IN.Supply.lines.Channel;

my $running = True;
$lines.closed.then: {$running = False}

while $running {
with $lines.poll() -> $line {
say "Process '$line'";
}
say "Do something Else.";
sleep ½;
}
say "I'm done.";
}

Note that the code above blocks at the my $lines = … line currently; so it doesn't start doing something until the first line comes in. To get around that you could do the following

my $lines = supply {
# unblock the $*IN.Supply.lines call
whenever start $*IN.Supply {
whenever .lines { .emit }
}
}.Channel;


Related Topics



Leave a reply



Submit