views:

1335

answers:

5
+8  Q: 

C fopen vs open

Is there any reason (other than syntactic ones) that you'd want to use

FILE *fdopen(int fd, const char *mode);

or

FILE *fopen(const char *path, const char *mode);

instead of

int open(const char *pathname, int flags, mode_t mode);

when using C in a Linux environment?

+4  A: 

If you have a FILE *, you can use functions like fscanf, fprintf and fgets etc. If you have just the file descriptor, you have limited (but likely faster) input and output routines read, write etc.

dreamlax
+3  A: 

open() is a low-level os call. fdopen() converts an os-level file descriptor to the higher-level FILE-abstraction of the C language. fopen() calls open() in the background and gives you a FILE-pointer directly.

There are several advantages to using FILE-objects rather raw file descriptors, which includes greater ease of usage but also other technical advantages such as built-in buffering. Especially the buffering generally results in a sizeable performance advantage.

Emil H
Are there any disadvantages to using the buffered 'f...' versions of open?
L. Moser
@L. Moser, yes, when you are already buffering the data, and hence the additional buffer adds unnecessary copying and memory overhead.
Michael Aaron Safyan
actually there are other disadvantages. `fopen()` does not provide the same level of control when opening files, for example create permissions, sharing modes, and more. typically `open()` and variants provide much more control, close to what the operating system actually provides
Matt Joiner
There are also the extreme cases where you `mmap` the file and do changes with normal I/O (as incredible as it sounds we do actually that in our project and for real good reasons), buffering would be in the way.
tristopia
A: 

Unless you're part of the 0.1% of applications where using open is an actual performance benefit, there really is no good reason not to use fopen. As far as fdopen is concerned, if you aren't playing with file descriptors, you don't need that call.

Stick with fopen and its family of methods (frwite, fread, fprintf, et al) and you'll be very satisfied. Just as importantly, other programmers will be satisfied with your code.

sixlettervariables
+13  A: 

There are four main reasons to use fopen instead of open.

  1. fopen provides you with buffering IO that may turn out to be a lot faster than what you're doing with open.
  2. fopen does line ending translation if the file is not opened in binary mode, which can be very helpful if your program is ever ported to a non-Unix environment.
  3. A FILE * gives you the ability to use fscanf and other stdio functions.
  4. Your code may someday need to be ported to some other platform that only supports ANSI C and does not support the open function.

In my opinion the line ending translation more often gets in your way than helps you, and the parsing of fscanf is so weak that you inevitably end up tossing it out in favor of something more useful.

And most platforms that support C have an open function.

That leaves the buffering question. In places where you are mainly reading or writing a file sequentially, the buffering support is really helpful and a big speed improvement. But it can lead to some interesting problems in which data does not end up in the file when you expect it to be there. You have to remember to fclose or fflush at the appropriate times.

If you're doing seeks, the usefulness of buffering quickly goes down.

Of course, my bias is that I tend to work with sockets a whole lot, and there the fact that you really want to be doing non-blocking IO (which FILE * totally fails to support in any reasonable way) with no buffering at all and often have complex parsing requirements really color my perceptions.

Omnifarious
I'm not going to question your experiences, but I'd love to hear you elaborate a bit on this. For what kind of applications do you feel that the built-in buffering gets in the way? What exactly is the problem?
Emil H
Didn't see the last paragraph. Valid point, IMHO. As far as I can tell the question was about file IO, though.
Emil H
Almost any program that does not stream IO, where you end up doing seeks into the middle of the file. I should update my response to clarify.
Omnifarious
So would it be correct to conclude that 'fgets' would block the thread until it reads a full line. And that non-buffered IO (such as read) would inherently not block the thread because they have no buffer to hold the data?
L. Moser
@L. Moser: No. The blocking and buffering are not strongly coupled. You would have to set the file descriptor to `O_NONBLOCK` with `fcntl` and and the `EAGAIN` error when `read` failed in order to avoid blocking a thread with `read`.
Omnifarious
To clarify when buffering gets in the way. It's when you use seek. The following read with whatever command (`fgets`, `fgetc`, `fscanf`, `fread`) , will always read the whole size of the buffer (4K, 8K or whatever you set). By using the direct I/O you can avoid that. In that case it's even better to use `pread` instead of a seek/read pair (1 syscall instead of 2).
tristopia
A: 

Using open, read, write means you have to worry about signal interaptions.

If the call was interrupted by a signal handler the functions will return -1 and set errno to EINTR.

So the proper way to close a file would be

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
digy