-3

The library I am working with requires a FILE* as the input to store an unknown amount of text. Normally I would be able to pass cout as the FILE*, but I want to capture this unknown sized text into a variable instead.

Is there a good way to create a FILE* to a growing sized buffer which is to be filled?

I am aware of something like this -

char output[1024] 
FILE *foutput = fmemopen(output, 1024, "w");

but from what I understand, this opens a fixed size buffer of 1024 bytes that can be written to.

CompEng88
  • 1,336
  • 14
  • 25
  • Are you looking for something like dynamically allocated memory? Or your issue is related to redirect standard output? – Adrian Maire Mar 24 '17 at 16:26
  • Possible duplicate of http://stackoverflow.com/questions/539537/memory-buffer-as-file/8908037 – kennytm Mar 24 '17 at 16:30
  • C is no OOP language. You cannot extend/overload operators or extend types. And `FILE` is an implementation-defined opaque type (resp. it should be treated as one). – too honest for this site Mar 24 '17 at 16:33
  • @Olaf: `QString` is `C++` not `C`. I guess the `C` tag is only because an answer in `C` would be acceptable. – Adrian Maire Mar 24 '17 at 16:34
  • @AdrianMaire: The code shown is C, so I commented about C. What is the problem with my comment? Did I say anything it would not be possible in C++? – too honest for this site Mar 24 '17 at 16:35
  • Please remove the tag of the unrelated language. Just because you use an example in one language, does not justify tagging with the language. If you want C++ features, why not use C++ streams? They are as much standard in C++ as the C functions are in C. – too honest for this site Mar 24 '17 at 16:37
  • Which language does the question want an answer for? C or C++? – JeremyP Mar 24 '17 at 16:49
  • @JeremyP: OP asks about `FILE`, which is C. I'd remove the C++ tag, but apparently the edit waits for acceptance. – too honest for this site Mar 24 '17 at 17:05
  • To answer your questions, the content of the answer can be C++ but I need to bring t down to FILE* to work with C code (my project is mixed) – CompEng88 Mar 24 '17 at 18:58

1 Answers1

2
char *ptr = NULL;
size_t size = 0;
FILE *fp = open_memstream(&ptr, &size);

Now you can use fp with stdio functions and access the "printed" output via ptr. The buffer is grown automatically and should be freed after fcloseing the stream.

open_memstream is not standard C but specified by POSIX.1-2008. There's an ISO C TR about it though.

For systems, where open_memstream isn't available (like macOS), you can implement it using fopencookie or funopen, which allow you to define your own fread, fwrite, fseek and fclose functions, which will be called while operating on the stream. Both aren't standardized (first is a GNU extension, second is BSD-specific).

You could use BSD libc's implementation on such systems.

For systems that only implement the API mandated by the C standard, you're out of luck. Best you can do is having the output written into a tempfile (Maybe kept in ramfs or similar) and then read from that.


You should only do this if you are interacting with an API that uses FILE IO though. If that's not a requirement consider using std::stringstream or similar instead.

a3f
  • 8,517
  • 1
  • 41
  • 46
  • I think this is pretty much a `glibc` only answer (OS X does not implement it). I don't think that is a problem for the questioner though because `fmemopen` is pretty much `glibc` only too. I'm not the downvoter btw, in fact, I upvoted. – JeremyP Mar 24 '17 at 16:57
  • @JeremyP `funopen` which is used to implement `open_memstream` is available on OS X. I amended my answer. – a3f Mar 24 '17 at 18:11
  • This is what I needed. Just 1 note -- I got a double free corruption after deleting ptr after fclose. I'm guessing fclose already takes care of freeing the resources? – CompEng88 Mar 28 '17 at 15:33
  • 1
    @ComputerEngineer88 POSIX prohibits `fclose` from doing that. What platform are you on? – a3f Mar 28 '17 at 19:41
  • CentOS 6.6 Linux version 2.6.32-504.23.4.el6.x86_64 gcc version 4.4.7. EDIT: I revise my answer. I tried it again and I believe I was deleting the FILE* instead of the char* after fclose. Deleting char* worked. Thank you for catching that for me. – CompEng88 Mar 30 '17 at 21:45