【发布时间】:2010-10-07 01:47:27
【问题描述】:
有没有办法将内存缓冲区创建为 FILE*。在 TiXml 中,它可以将 xml 打印到 FILE* 但我似乎无法将其打印到内存缓冲区。
【问题讨论】:
有没有办法将内存缓冲区创建为 FILE*。在 TiXml 中,它可以将 xml 打印到 FILE* 但我似乎无法将其打印到内存缓冲区。
【问题讨论】:
有一种 POSIX 方法可以将内存用作 FILE 描述符:fmemopen 或 open_memstream,具体取决于您想要的语义:Difference between fmemopen and open_memstream
【讨论】:
我想正确的答案是凯文。但这里有一个用 FILE *.请注意,如果缓冲区大小(此处为 100000)太小,则会丢失数据,因为在刷新缓冲区时会写出数据。此外,如果程序调用 fflush() 会丢失数据。
#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]);
}
}
【讨论】:
setbuf() 和 setvbuf()(不是 setbuffer())是 ISO-C,所以一旦你使用它们,它应该是可移植的。如果缓冲模式是完全缓冲的,则应该尝试将缓冲区完全填满;在 Windows 上,您必须使用“NUL”而不是“/dev/null”;您还应该以二进制模式“wb”打开文件
fmemopen 可以从缓冲区创建文件,这对你有意义吗?
【讨论】:
我写了一个如何创建内存文件的简单示例:
#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("");
}
【讨论】:
C++ basic_streambuf继承
在 C++ 中,如果可以,您应该避免使用FILE*。
仅使用 C++ 标准库,可以创建一个透明地使用文件或内存 IO 的单一接口。
这使用了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);
}
}
不幸的是,FILE* 和 fstream 似乎无法互换:Getting a FILE* from a std::fstream
【讨论】:
ostreambuf 构造函数中,您也可以设置setg 以从流中读取。例如this->setg(buffer, buffer, buffer + bufferLength);
您可以使用文档所述的TiXMLPrinter 的CStr 方法:
TiXmlPrinter 非常有用 需要:
- 打印到内存(尤其是在非 STL 模式下)
- 控制格式(行尾等)
【讨论】:
https://github.com/Snaipe/fmem 是针对不同平台/版本特定的内存流实现的包装器
它依次尝试以下实现:
当没有其他方法可用时,fmem 回退到 tmpfile()
【讨论】: