简体   繁体   中英

Is it necessary to use a while loop when using the read and write system calls?

I am practicing the read and write system call, the below code is working fine with a while loop and also without them. could you please tell me what is the use of while loop here, is it necessary to add it while using read and write system calls. I am a beginner. Thanks.

#include <unistd.h>
#define BUF_SIZE 256
int main(int argc, char *argv[])
{
    char buf[BUF_SIZE];    
    ssize_t rlen;
    int i; 
    char from;
    char to;
    from = 'e';
    to = 'a';

    while (1) {
        rlen = read(0, buf, sizeof(buf));
        if (rlen == 0)
               return 0;

        for (i = 0; i < rlen; i++) {
               if (buf[i] == from)
                      buf[i] = to;
        }
    write(1, buf, rlen);
   }
return 0;
}


You usually need to use while loops (or some kind of loop in general) with read and write , because, as you should know from the manual page ( man 2 read ):

 RETURN VALUE On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of- file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. See also NOTES.

Therefore, if you ever want to read more than 1 byte, you need to do this in a loop, because read can always process less than the requested amount.

Similarly, write can also process less than the requested size (see man 2 write ):

 RETURN VALUE On success, the number of bytes written is returned (zero indicates nothing was written). It is not an error if this number is smaller than the number of bytes requested; this may happen for example because the disk device was filled. See also NOTES. On error, -1 is returned, and errno is set appropriately.

The only difference here is that when write returns 0 it's not an error or an end of file indicator, you should just retry writing.

Your code is almost correct, in that it uses a loop to keep reading until there are no more bytes left to read (when read returns 0 ), but there are two problems:

  1. You should check for errors after read ( rlen < 0 ).
  2. When you use write you should also add a loop there too, because as I just said, even write could process less than the requested amount of bytes.

A correct version of your code would be:

#include <stdio.h>
#include <unistd.h>

#define BUF_SIZE 256

int main(int argc, char *argv[])
{
    char buf[BUF_SIZE];
    ssize_t rlen, wlen, written;
    char from, to;
    int i;

    from = 'e';
    to = 'a';

    while (1) {
        rlen = read(0, buf, sizeof(buf));

        if (rlen < 0) {
            perror("read failed");
            return 1;
        } else if (rlen == 0) {
            return 0;
        }

        for (i = 0; i < rlen; i++) {
            if (buf[i] == from)
                buf[i] = to;
        }

        for (written = 0; written < rlen; written += wlen) {
            wlen = write(1, buf + written, rlen - written);

            if (wlen < 0) {
                perror("write failed");
                return 1;
            }
        }
    }

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM