11

I'm trying to read binary data in a C program with read() but EOF test doesn't work. Instead it keeps running forever reading the last bit of the file.

#include <stdio.h>
#include <fcntl.h>
int main() {

  // writing binary numbers to a file
  int fd = open("afile", O_WRONLY | O_CREAT, 0644);
  int i;
  for (i = 0; i < 10; i++) {
    write(fd, &i, sizeof(int));
  }
  close(fd);

  //trying to read them until EOF
  fd = open("afile", O_RDONLY, 0);
  while (read(fd, &i, sizeof(int)) != EOF) {
    printf("%d", i);
  }
  close(fd);
}
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
sekmet64
  • 1,635
  • 4
  • 19
  • 30
  • 2
    Not the imediate problem (read returns 0, not EOF) but you probably ought to get into the habit of compiling with `gcc -Wall`, take note of warnings (and fix them !), and `#include ` when using `read`/`write`. – Paul R Jul 05 '10 at 14:20
  • thanks for the advice, i have that included in my main code where i needed this but gonna use the -Wall too from now on :) – sekmet64 Jul 05 '10 at 14:25

3 Answers3

24

read returns the number of characters it read. When it reaches the end of the file, it won't be able to read any more (at all) and it'll return 0, not EOF.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • ugh :S don't know how did i miss that in the manual, been reading about it in the past 20 minutes Thanks! – sekmet64 Jul 05 '10 at 14:15
  • 2
    Well, I can see how it is not obvious. After all, one could think of plenty of reasons why 0 bytes might be read. The key is that when read encounters an error, it _always_ returns -1, and never 0. returning 0 is success, end of file. AFAICT, even for non-blocking IO, where it is possible, and sometimes very likely 0 bytes will be read, 0 is only returned when EOF is reached. The rest of the time, when there are zero bytes to be read and EOF has _not_ been reached, -1 is returned and errno=EAGAIN. At least, that is my understanding. – enigmaticPhysicist Apr 08 '14 at 19:35
3

You must check for errors. On some (common) errors you want to call read again!

If read() returns -1 you have to check errno for the error code. If errno equals either EAGAIN or EINTR, you want to restart the read() call, without using its (incomplete) returned values. (On other errors, you maybe want to exit the program with the appropriate error message (from strerror))

Example: a wrapper called xread() from git's source code

u0b34a0f6ae
  • 48,117
  • 14
  • 92
  • 101
0

POSIX rasys return == 0 for end of file

http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html

If no process has the pipe open for writing, read() shall return 0 to indicate end-of-file.

This confirms Jerry's answer.

EOF is returned by some ANSI functions, e.g. man getc says:

fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error.

ungetc() returns c on success, or EOF on error.

so you still can't use it to distinguish error and end of file in that case, feof is needed.

See also: How to use EOF to run through a text file in C?

Community
  • 1
  • 1
Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985