2011-05-02 158 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