Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

read() from stdin

Tags:

c

linux

io

unix

Consider the following line of code:

while((n = read(STDIN_FILENO, buff, BUFSIZ)) > 0)

As per my understanding read/write functions are a part of non-buffered I/O. So does that mean read() function will read only one character per call from stdio? Or in other words, the value of n will be

    -1  in case of error
n =  0  in case of EOF
     1  otherwise

If it is not the case, when would the above read() function will return and why?

Note: I was also thinking that read() will wait until it successfully reads BUFSIZ number of characters from stdin. But what happens in a case number of characters available to read are less than BUFSIZ? Will read wait forever or until EOF arrives (Ctrl + D on unix or Ctrl + Z on windows)?

Also, lets say BUFSIZ = 100 and stdin = ACtrl+D (i.e EOF immediately following a single character). Now how many times the while loop will iterate?

like image 700
Ravi Gupta Avatar asked Jan 23 '12 17:01

Ravi Gupta


People also ask

What is read from stdin?

Short for standard input, stdin is an input stream where data is sent to and read by a program. It is a file descriptor in Unix-like operating systems, and programming languages, such as C, Perl, and Java. Below, is an example of how STDIN could be used in Perl.

How do you read a character from stdin?

The built-in function in c programming is getline() which is used for reading the lines from the stdin. But we can also use other functions like getchar() and scanf() for reading the lines.

What does read () in C do?

The read() function reads data previously written to a file. If any portion of a regular file prior to the end-of-file has not been written, read() shall return bytes with value 0. For example, lseek() allows the file offset to be set beyond the end of existing data in the file.

What is read input from stdin Python?

stdin is a file-like object on which you can call functions read or readlines if you want to read everything or you want to read everything and split it by newline automatically. (You need to import sys for this to work.) If you want to prompt the user for input, you can use raw_input in Python 2.


2 Answers

The way read() behaves depends on what is being read. For regular files, if you ask for N characters, you get N characters if they are available, less than N if end of file intervenes.

If read() is reading from a terminal in canonical/cooked mode, the tty driver provides data a line at a time. So if you tell read() to get 3 characters or 300, read will hang until the tty driver has seen a newline or the terminal's defined EOF key, and then read() will return with either the number of characters in the line or the number of characters you requested, whichever is smaller.

If read() is reading from a terminal in non-canonical/raw mode, read will have access to keypresses immediately. If you ask read() to get 3 characters it might return with anywhere from 0 to 3 characters depending on input timing and how the terminal was configured.

read() will behave differently in the face of signals, returning with less than the requested number of characters, or -1 with errno set to EINTR if a signal interrupted the read before any characters arrived.

read() will behave differently if the descriptor has been configured for non-blocking I/O. read() will return -1 with errno set to EAGAIN or EWOULDBLOCK if no input was immediately available. This applies to sockets.

So as you can see, you should be ready for surprises when you call read(). You won't always get the number of characters you requested, and you might get non-fatal errors like EINTR, which means you should retry the read().

like image 120
Kyle Jones Avatar answered Oct 19 '22 21:10

Kyle Jones


Your code reads:

while((n = read(0, buff, BUFSIZ) != 0))

This is flawed - the parentheses mean it is interpreted as:

while ((n = (read(0, buff, BUFSIZ) != 0)) != 0)

where the boolean condition is evaluated before the assignment, so n will only obtain the values 0 (the condition is not true) and 1 (the condition is true).

You should write:

while ((n = read(0, buff, BUFSIZ)) > 0)

This stops on EOF or a read error, and n lets you know which condition you encountered.


Apparently, the code above was a typo in the question.

Unbuffered I/O will read up to the number of characters you read (but not more). It may read less on account of EOF or an error. It may also read less because less is available at the time of the call. Consider a terminal; typically, that will only read up to the end of line because there isn't any more available than that. Consider a pipe; if the feeding process has generated 128 unread bytes, then if BUFSIZ is 4096, you'll only get 128 bytes from the read. A non-blocking file descriptor may return because nothing is available; a socket may return fewer bytes because there isn't more information available yet; a disk read may return fewer bytes because there are fewer than the requested number of bytes left in the file when the read is performed.

In general, though, read() won't return just one byte if you request many bytes.

like image 5
Jonathan Leffler Avatar answered Oct 19 '22 21:10

Jonathan Leffler