96

I'm playing around with mkstemp(), which provides a file descriptor, but I want to generate formatted output via fprintf(). Is there an easy way to transform the file descriptor provided by mkstemp() into a FILE * structure that is suitable for use with fprintf()?

roschach
  • 8,390
  • 14
  • 74
  • 124
BD at Rivenhill
  • 12,395
  • 10
  • 46
  • 49
  • 6
    And the inverse: [How can I convert a file pointer ( FILE* ) to a file descriptor (fd)?](http://stackoverflow.com/questions/3167298/how-can-i-convert-a-file-pointer-file-to-a-file-descriptor-fd) – Michael Burr Oct 01 '13 at 20:37

3 Answers3

120

Use fdopen():

FILE* fp = fdopen(fd, "w");
Richard Pennington
  • 19,673
  • 4
  • 43
  • 72
  • 36
    And to get the file descriptor from a FILE* use `fileno()` : http://linux.die.net/man/3/fileno – Lee Netherton Oct 17 '11 at 14:28
  • 3
    if `fd` was opened with some flags (like `O_NONBLOCK`) -- what will happen with them after `fdopen` opens it with new flags? Will they be `xor`-ed together or substituted? – xealits Nov 04 '15 at 19:09
  • Not available in ANSI C. – jww Mar 26 '16 at 23:28
  • 5
    @jww: File descriptors are not ANSI C to begin with. – Rufflewind May 02 '16 at 01:08
  • and is there a way to close a file with the fd? – Jéssica Carneiro Jan 30 '17 at 21:44
  • If you mean close(fd), that's not a good idea. fclose(fp) should be used to make sure any buffered output (if any) is written. – Richard Pennington Jan 31 '17 at 00:10
  • 2
    is it bad in any way to call `fdopen` multiple times? (assuming it happens inside some function which gets called again and again) – phil294 Jul 04 '17 at 23:08
  • You don't want to fdopen() the same file descriptor twice. Each instance will have separate buffers that will cause your input/output to get messed up. – Richard Pennington Jul 05 '17 at 13:44
  • @RichardPennington I think multiple `fdopen` calls are fine depending on what underlies the file descriptor. For a tty or a socket this may actually be desirable since ANSI C has requirements for `fseek`/`fgetpos`/`fflush` calls between input and output. Here it seems different streams for input and output are the best way to go. This essentially happens with `stdin`/`stdout`/`stderr` anyway on a terminal device - the file descriptors refer to the same file description. See https://www.experts-exchange.com/questions/24261206/Using-fdopen-twice-on-an-open-stream-socket-file-descriptor.html – Graeme Oct 21 '17 at 21:16
  • 2
    @xealits The options for the FILE* have to be within the scope of the already open file descriptor. So if you have opened fd with read only, and the FILE* with write only, it should throw an exception. For more info refer to https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxbd00/rtfdo.htm – Tjad Clark Dec 06 '17 at 07:59
  • 1
    @TjadClark "it should throw an exception" - that would be difficult seeing as fdopen() is a C function and C has no native exceptions mechanism. – Nick Oct 01 '18 at 15:07
32

FILE* f = fdopen(d, "w");

man fdopen output:

SYNOPSIS

#include <stdio.h>

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

The fdopen() function associates a stream with the existing file descriptor, fildes. The mode of the stream must be compatible with the mode of the file descriptor. When the stream is closed via fclose(3), fildes is closed also.

Gregory Pakosz
  • 69,011
  • 20
  • 139
  • 164
-8

There is no standard way of doing this (or the reverse) as the C Standard has nothing to say about file descriptors. Your specific platform may or may not provide such a mechanism.

  • 18
    Depends on what you mean by "standard". POSIX is a standard. – Richard Pennington Dec 21 '09 at 17:33
  • 6
    though, The fdopen() function conforms to IEEE Std 1003.1-1988 (``POSIX.1''). – Gregory Pakosz Dec 21 '09 at 17:34
  • 12
    The question was about file descriptors. ;-) – Richard Pennington Dec 21 '09 at 17:35
  • 4
    @Neil > you might be right, you didn't help the OP with your answer – Gregory Pakosz Dec 21 '09 at 17:35
  • 1
    @Gregory I helped him assuming that he wants to write portable code. And downvoting technically correct answers is not good practice. –  Dec 21 '09 at 17:38
  • 1
    @Richard The question is tagged as C, not Posix. Posix is a platform, not a language, standard. –  Dec 21 '09 at 17:39
  • @Neil > I didn't vote down, indeed there is nothing wrong in what you said. – Gregory Pakosz Dec 21 '09 at 17:40
  • 11
    @Neil > the question being tagged as C doesn't mean "tell me the holly truth about the C standard" but rather "I'm coding in C, I fail at doing this, please tell me whether it is possible and how?" – Gregory Pakosz Dec 21 '09 at 17:42
  • There is a `posix` tag here on SO, with 193 questions. Having said that, I think Neil's answer is correct. More people should be using `posix` tag. And it's a good idea to remind people what exactly "C" is. While we're at it, we should make people realize that there's nothing like "C/C++", and that these are two different languages. – Alok Singhal Dec 21 '09 at 17:53
  • 1
    @Neil > it looks like you have fans though, as several of my answers are being downvoted right now :) – Gregory Pakosz Dec 21 '09 at 17:57
  • 1
    I'm backing away slowly... Now turning and running away. – Richard Pennington Dec 21 '09 at 17:59
  • @Gregory: For the record, it wasn't me. There are some weird downvoting issues here on SO. My posts http://stackoverflow.com/questions/1898371/problems-writing-the-memset-function/1898515#1898515 and http://stackoverflow.com/questions/1938491/memory-corruption/1938530#1938530 were downvoted, and I don't know why! – Alok Singhal Dec 21 '09 at 17:59
  • 8
    I agree that there's no standard way of doing this, but the OP's mention of `mkstemp` implies that non-standard solutions are acceptable in this particular instance. In that case, however, he should have added the `posix` tag (which I see has since been added). – Emerick Rogul Dec 21 '09 at 17:59
  • 9
    @Neil, and the purpose of the Net and the meaning of life. You would make more sense if you've said that you are of different opinion. I also doubt SO is all about hairsplitting over standards. And it's not very practical to rely on tagging skills of someone with an SO-experience corresponding to the reputation of 23. – Michael Krelin - hacker Dec 21 '09 at 18:08
  • Not sure why this fellow is getting downvoted. ANSI C does not have `fdopen`, so there's no way to convert a file descriptor to a `FILE*` in a base system. You'd need a different standard to get the functionality. – jww Mar 26 '16 at 23:27