49

What are the possible ways for reading user input using read() system call in Unix. How can we read from stdin byte by byte using read()?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bunny Bunny
  • 745
  • 2
  • 6
  • 9
  • 2
    your should read in `read()` manual – Grijesh Chauhan Apr 08 '13 at 15:50
  • 1
    Read will do this just fine, but depending on exactly what you want to do, you may find that you have to do more than just call read - can you post your code, and explain exactly which part you have problems with? – Mats Petersson Apr 08 '13 at 15:53
  • I agree with Mats, what *excatly* are you looking for here? Where is the problem? [There are](http://stackoverflow.com/questions/9610064/read-stdin-in-c) also a lot of different [examples](http://stackoverflow.com/questions/7503399/reading-from-stdin-using-read-and-figuring-out-the-size-of-the-buffer) of how to do [this on SO](http://stackoverflow.com/questions/1237329/read-from-stdin-doesnt-ignore-newline), do you do any searching before asking the question? – Mike Apr 08 '13 at 16:09

2 Answers2

55

You can do something like this to read 10 bytes:

char buffer[10];
read(STDIN_FILENO, buffer, 10);

remember read() doesn't add '\0' to terminate to make it string (just gives raw buffer).

To read 1 byte at a time:

char ch;
while(read(STDIN_FILENO, &ch, 1) > 0)
{
 //do stuff
}

and don't forget to #include <unistd.h>, STDIN_FILENO defined as macro in this file.

There are three standard POSIX file descriptors, corresponding to the three standard streams, which presumably every process should expect to have:

Integer value   Name
       0        Standard input (stdin)
       1        Standard output (stdout)
       2        Standard error (stderr)

So instead STDIN_FILENO you can use 0.

Edit:
In Linux System you can find this using following command:

$ sudo grep 'STDIN_FILENO' /usr/include/* -R | grep 'define'
/usr/include/unistd.h:#define   STDIN_FILENO    0   /* Standard input.  */

Notice the comment /* Standard input. */

Johnny Mnemonic
  • 3,822
  • 5
  • 21
  • 33
  • why in the manpage, it uses the word "shall attempt". Is there any case that read will not read exactly the number of bytes specified by the 3rd argument? https://linux.die.net/man/3/read – weefwefwqg3 Nov 13 '17 at 01:08
  • 1
    @weefwefwqg3 read() will read fewer bytes than requested if it is interrupted by a signal, or if there are fewer bytes available than requested, etc. – camerondm9 Feb 17 '19 at 01:32
15

From the man read:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

Input parameters:

  • int fd file descriptor is an integer and not a file pointer. The file descriptor for stdin is 0

  • void *buf pointer to buffer to store characters read by the read function

  • size_t count maximum number of characters to read

So you can read character by character with the following code:

char buf[1];

while(read(0, buf, sizeof(buf))>0) {
   // read() here read from stdin charachter by character
   // the buf[0] contains the character got by read()
   ....
}
Community
  • 1
  • 1
MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • 2
    You could use `int fileno(FILE *stream)` first – Grijesh Chauhan Apr 08 '13 at 15:57
  • @Grijesh - You can take it one step further, `stdin` is going to be 0, so you can just `read(0,...` Don't need to search around for `stdin`'s file number on *NIX systems – Mike Apr 08 '13 at 16:15
  • @Mike Yes I `stdin = 0`, `stdout = 1`, `stderr = 2` and good is its same for all OS. – Grijesh Chauhan Apr 08 '13 at 16:24
  • @MOHAMED wait don't delete your answer., after some time I would add some details. – Grijesh Chauhan Apr 08 '13 at 16:47
  • @GrijeshChauhan I m not going to do it I updated it based on your remarks – MOHAMED Apr 08 '13 at 16:53
  • @MOHAMED Go ahead MOHAMED to improve your answer: add two points (1) you can just read using `char c`; `read(0, &c, 1)` , (2) read() function doesn't terminate input buffer with `\0` with `fgets()` do. So in case if someone wants to use buffer as string he has to explicitly add null like: `no_byte = read(0, buffer, sizeof(buffer)-1); buffer[no_bytes] = '\0';` This is the point where new guys do mistakes. like in [this question](http://stackoverflow.com/questions/15847472/udp-client-receiving-a-text-file/15847675#15847675) read second error...go ahead this is what I wanted to add. – Grijesh Chauhan Apr 08 '13 at 17:10
  • why in the manpage, it uses the word "shall attempt". Is there any case that read will not read exactly the number of bytes specified by the 3rd argument? https://linux.die.net/man/3/read – weefwefwqg3 Nov 13 '17 at 01:09