clinuxfile-iofopen

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?


Solution

  • Of those, fdopen is not like the others. fdopen is what you would use if you first called open and then wanted a FILE *. There is no sense doing that if you have the choice to just call fopen instead. There are cases where you won't be able to get fopen to do exactly what you want, but they're outside the scope of this question.

    So, let's just pretend fdopen isn't even there and get on with the question.

    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 (though the world appears to be converging on LF-only (except IETF text-based networking protocols like SMTP and HTTP and such)).
    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 (and experience) 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 (aka fsetpos or fseek the second of which is slightly trickier to use in a standards compliant way), 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.