Is there any way to create a memory buffer as a FILE*. In TiXml it can print the xml to a FILE* but i cant seem to make it print to a memory buffer.
-
1Also see [Difference between fmemopen and open_memstream](https://stackoverflow.com/q/29849749/608639). – jww Jun 20 '17 at 21:36
-
[C - create file in memory](https://stackoverflow.com/q/12249610/995714), [How to map BYTE array as FILE * on Windows](https://stackoverflow.com/q/46836658/995714) – phuclv Apr 23 '19 at 10:45
7 Answers
There is a POSIX way to use memory as a FILE
descriptor: fmemopen
or open_memstream
, depending on the semantics you want: Difference between fmemopen and open_memstream

- 347,512
- 102
- 1,199
- 985

- 2,089
- 13
- 14
-
9
-
17POSIX is NOT a C/C++ standard! It's a standard that is heavily dependent on the C-standard, but nonetheless only works on a subset of the OSs that are supported by/developed in C/C++! Not to mention that POSIX conflicts with certain aspects of the C/C++ standards... – MFH Jul 17 '12 at 15:02
-
2So...we're *not*, in general, programming on systems which implement POSIX? You certainly could have fooled me. I suppose I should have taken your multiple uses of exclamation points to mean that you are totally The Authority here. – tbert Jul 17 '12 at 18:39
-
2If you consider Win32 (not another NT subsystem [like SUA] or an additional layer ontop of Win32 [like Cygwin]) to follow POSIX, then maybe we are... (you certainly would be alone with that definition...) In all other cases we are not in general programming on a POSIX-compliant OS... – MFH Jul 18 '12 at 10:54
-
So, an OS which explicitly does not attempt to implement a standard, does not implement said standard? Did you have a point, or were you too busy not punching the exclamation point to consider developing one? – tbert Jul 19 '12 at 11:37
-
9How are we all "in general, programming on systems which implement POSIX" if the major desktop operating system does not follow POSIX? My point is that neither fmemopen or open_memstream are defined by any C/C++ standard! - which you claimed and backed with POSIX 200809 - therefor claiming that they are "standards-compliant" is simply untrue. It's funny how your only reaction so far has been to mention my "massive" use of exclamation points in every comment instead of admitting that the claim that these functions are standards-compliant is wrong... – MFH Jul 19 '12 at 15:57
-
3No they are not! They are not in the C/C++ standards, therefore they are anything but standards compliant, simple as that. I thought I was talking with someone that cared about C/C++, seemed I was wrong. (You know, these languages aren't limited to the OS of your preference. Not to mention it wasn't the Windows guy that claimed that non-standard extensions were part of the standard...) – MFH Jul 19 '12 at 20:45
-
4"The good thing about standards is that there are so many to choose from." I suppose living in the real world, vice the pure nirvana of the C apostle, will have to soothe my conscience. – tbert Jul 20 '12 at 04:20
-
4that quote is true, nonetheless neither of these functions is defined in the C/C++ standard... (and these two are the only ones relevant in terms of the original question) – MFH Jul 20 '12 at 18:18
-
3
-
3@tbert: It's 2017 and I am coding for a non-POSIX-compliant platform. – asfdfdfd Jan 04 '17 at 02:50
-
1
I guess the proper answer is that by Kevin. But here is a hack to do it with FILE *. Note that if the buffer size (here 100000) is too small then you lose data, as it is written out when the buffer is flushed. Also, if the program calls fflush() you lose the data.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *f = fopen("/dev/null", "w");
int i;
int written = 0;
char *buf = malloc(100000);
setbuffer(f, buf, 100000);
for (i = 0; i < 1000; i++)
{
written += fprintf(f, "Number %d\n", i);
}
for (i = 0; i < written; i++) {
printf("%c", buf[i]);
}
}

- 25,136
- 3
- 52
- 71
-
1It works only if can prevent stdio from flushing the buffer, and I guess the details of that aren't standardized. – Antti Huima Feb 12 '09 at 02:50
-
11`setbuf()` and `setvbuf()` (NOT `setbuffer()`) are ISO-C, so it *should* be portable once you use these. If the bufferering mode is fully buffered, it should try to fill the buffer completely; on windows, you have to use "NUL" instead of "/dev/null"; you should also open the file in binary mode "wb" – Christoph Feb 12 '09 at 11:02
I wrote a simple example how i would create an in-memory FILE:
#include <unistd.h>
#include <stdio.h>
int main(){
int p[2]; pipe(p); FILE *f = fdopen( p[1], "w" );
if( !fork() ){
fprintf( f, "working" );
return 0;
}
fclose(f); close(p[1]);
char buff[100]; int len;
while( (len=read(p[0], buff, 100))>0 )
printf(" from child: '%*s'", len, buff );
puts("");
}

- 2,436
- 1
- 16
- 13
C++ basic_streambuf
inheritance
In C++, you should avoid FILE*
if you can.
Using only the C++ stdlib, it is possible to make a single interface that transparently uses file or memory IO.
This uses techniques mentioned at: Setting the internal buffer used by a standard stream (pubsetbuf)
#include <cassert>
#include <cstring>
#include <fstream>
#include <iostream>
#include <ostream>
#include <sstream>
/* This can write either to files or memory. */
void write(std::ostream& os) {
os << "abc";
}
template <typename char_type>
struct ostreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> > {
ostreambuf(char_type* buffer, std::streamsize bufferLength) {
this->setp(buffer, buffer + bufferLength);
}
};
int main() {
/* To memory, in our own externally supplied buffer. */
{
char c[3];
ostreambuf<char> buf(c, sizeof(c));
std::ostream s(&buf);
write(s);
assert(memcmp(c, "abc", sizeof(c)) == 0);
}
/* To memory, but in a hidden buffer. */
{
std::stringstream s;
write(s);
assert(s.str() == "abc");
}
/* To file. */
{
std::ofstream s("a.tmp");
write(s);
s.close();
}
/* I think this is implementation defined.
* pusetbuf calls basic_filebuf::setbuf(). */
{
char c[3];
std::ofstream s;
s.rdbuf()->pubsetbuf(c, sizeof c);
write(s);
s.close();
//assert(memcmp(c, "abc", sizeof(c)) == 0);
}
}
Unfortunately, it does not seem possible to interchange FILE*
and fstream
: Getting a FILE* from a std::fstream

- 1
- 1

- 347,512
- 102
- 1,199
- 985
-
1Don't forget in the `ostreambuf` constructor you can set the `setg` for reading from the stream too. e.g. `this->setg(buffer, buffer, buffer + bufferLength);` – E-rich Jan 27 '21 at 20:24
You could use the CStr method of TiXMLPrinter which the documentation states:
The TiXmlPrinter is useful when you need to:
- Print to memory (especially in non-STL mode)
- Control formatting (line endings, etc.)

- 7,483
- 3
- 28
- 33
https://github.com/Snaipe/fmem is a wrapper for different platform/version specific implementations of memory streams
It tries in sequence the following implementations:
- open_memstream.
- fopencookie, with growing dynamic buffer.
- funopen, with growing dynamic buffer.
- WinAPI temporary memory-backed file.
When no other mean is available, fmem falls back to tmpfile()

- 185
- 1
- 10