The Difference between File Descriptors and Streams in Linux

Written by Ian on Friday 27/04/07

In UNIX there are two basic mechanisms for reading and writing:

File descriptors

int fd;

  • Primitive low-level interface

  • Many control options & special modes



FILE *fp;

  • Higher level abstraction - built on top of file descriptors

  • Three types of buffering

  • Lots of functions for handling & processing streams

  • Very portable to other systems

IMPORTANT: don't use BOTH simultaneously for the same file while you can grab the file descriptor from within the FILE * struture, it's confusing to use this to say the least!! Normally when you mix the two up you just get a compile time error (or worse, a wierd runtime error!).

Here are the file descriptor commands

int fd;
read(fd, &buffer, 100);
write(fd, &buffer, 100);

Not much choice is there? But look at streams..

A selection of streams commands

FILE *fp;
fread(&buffer, 1, 100, fp);
fwrite(&buffer, 1, 100, fp);
fprintf(fp, ‘hello %s\\\\n’, name);
fscanf(fp, ":>%d", &value);
fgets(&buffer, 100, fp);
fputs(&buffer, fp);
rewind, fseek, ftell...
fgetpos, fsetpos and more...

To recap, use file descriptors for simple low-level access, but if you want to use more complex functions, you have to use streams.

One more important point - if you want to open a file in a special way, such as NON-BLOCKING, then you must use file descriptors, you just can't do it with streams!

You would open a read only file in non-blocking mode like this:

fd = open("/dev/mypipe", O_RDONLY | O_NONBLOCK);

Don't know what non-blocking means?? Check out my *next* article!