2011-05-02 132 views
8

我正在使用一个函数库,其中有很多函数可以写入FILE,但似乎并不方便将相同数据转储到内存中的对象。有什么办法可以创建一个将数据存储在内存中而不是写入磁盘的对象(或覆盖它) - 我想避免一次又一次地打开/写入/读取文件的性能。不写入磁盘的C++文件

UPDATE:每罗布的建议,试图字符串流:

ss.put(c); 

std::string myval = ss.str(); 

printf("Value: %s\n after writing: %i length %lu\n",myval.c_str(),c, myval.length()); 

但是,现在正试图获取数据(二进制)从字符串流的有我卡住 - 我怎么抢二进制数据我已经添加?

+1

只为完整性起见,我提['标准:: stringstream'(http://www.cplusplus.com/reference/iostream/stringstream/) 。 'stringstream'不会解决OP的问题,因为他被绑定到'FILE'。如果他可以修改他的库,他可以使用'stringstream'。 – 2011-05-02 17:56:44

+0

@Rob - 我的目标是避免修改库的来源(以避免升级时发生冲突等),但我确实有选择。我想我可能会采取这种方式,因为其他解决方案现在看起来比我的C技术更低级。 基本上,我需要替换或增加一个现在使用'fputc'的函数 - 我将使用'stringstream'中的'put'来代替,对吗? – 2011-05-02 18:28:09

+0

不要害怕使用'fmemopen'或'open_memstream'。他们看起来像你的完美解决方案。但是,如果你确实想使用'stringstream',请看我的答案。 – 2011-05-02 19:04:42

回答

10

除了已经提到的GNU的fmemopen(),这是在POSIX称为open_memstream ,类似的解决方案可以组合而得到 mmap()(使用MAP_ANONYMOUS)或者返回文件描述符的存储器块的任何其它特定于操作系统的功能,和 fdopen()

编辑:这是错误的,mmap不会创建文件描述符。

+0

很好的答案。我有限的C技能让我很担心这个问题会发生 - 尽管在原文中看到我对Rob的评论。只需对原始图书馆进行一些小修改就可以脱身。 – 2011-05-02 18:31:34

+0

你是如何从mmap获得可以与fdopen一起使用的文件描述符的?我试图让一个FILE指针指向内存中没有备份文件的mmap'd位置。 – featherless 2012-06-25 01:12:56

+0

@featherless你说得对,'mmap'不会创建文件描述符。在编写时我正在考虑'shm_open',但'fdopen'中不允许使用'shm_open'的文件描述符。谢谢你指出错误! – Cubbi 2012-06-25 16:24:00

5

GNU libc有例如fmemopen,它会给你一个写入内存的FILE *。有关详细信息,请在您的Linux系统上尝试man fmemopen

我怀疑(但肯定不知道)fmemopen是一种包装器,它协调了@Cubbi提到的方法mmap/fdopen

0

考虑安装一个tmpfs并让应用程序写入它。当然这只是* nix。

1

如果您可以选择修改库,则可以使用C++流而不是C FILE流。

如果你的老图书馆的功能是这样的:

void SomeFun(int this, int that, FILE* logger) { 
    ... other code ... 
    fprintf(logger, "%d, %d\n", this, that); 
    fputs("Warning Message!", logger); 
    char c = '\n'; 
    fputc(c, logger); 
} 

你可能会替换该代码:

void SomeFun(int this, int that, std::ostream& logger) { 
    ... other code ... 
    logger << this << ", " << that << "\n"; 
    // or: logger << boost::format("%d %d\n") %this %that; 
    logger << "Warning Message!"; 
    char c = '\n'; 
    logger.put(c); 
    // or: logger << c; 
} 

然后,在您的非图书馆的代码,这样做:

#include <sstream>  
std::stringstream logStream; 
SomeFun(42, 56, logStream); 
DisplayCStringOnGui(logStream.str().c_str()); 
+0

编辑:把代码放在更好的格式化的原始问题 我已经得到它的工作,达到一个基本点。我现在遇到的问题是获取数据 - 它是二进制数据。现在,我有: 'ss.put(c); std :: string myval = ss.str(); ()调用给我一个值( ) printf(“Value:%s \ n after writing:%i length%lu \ n”,myval.c_str(),c,myval.length());' length准确地增加,但我坚持试图获取数据 - c_str给我一个长度为4的“const char *” - 缺少大部分二进制数据 – 2011-05-02 19:31:03

+1

如果库返回的数据是二进制(也就是可能嵌入了''0''字符),那么你将无法使用'printf(“%s”,...)'来访问它。你只是试图显示这些数据?或者你需要将它传递给另一个函数?你可以像这样逐字节访问数据:'myval [i]'。或者你可以传递一个像这样的数据的指针:'MyFunc(myval.data(),myval.length())'。 – 2011-05-02 19:39:21