2009-11-16 9 views
5

मैं कुछ फ़ंक्शन में FILE * में पास करने का एक तरीका ढूंढ रहा हूं ताकि फ़ंक्शन fprintf के साथ इसे लिख सके। यह आसान है अगर मैं डिस्क पर वास्तविक फ़ाइल में आउटपुट चालू करना चाहता हूं, तो कहें। लेकिन इसके बजाय मैं सभी आउटपुट को स्ट्रिंग के रूप में प्राप्त करना चाहता हूं (char *)। एपीआई की तरह मैं चाहता है:एक FILE * स्ट्रीम बनाना जिसके परिणामस्वरूप स्ट्रिंग

/** Create a FILE object that will direct writes into an in-memory buffer. */ 
FILE *open_string_buffer(void); 

/** Get the combined string contents of a FILE created with open_string_buffer 
    (result will be allocated using malloc). */ 
char *get_string_buffer(FILE *buf); 

/* Sample usage. */ 
FILE *buf; 
buf = open_string_buffer(); 
do_some_stuff(buf); /* do_some_stuff will use fprintf to write to buf */ 
char *str = get_string_buffer(buf); 
fclose(buf); 
free(str); 

glibc हेडर दर्शाता है कि एक फ़ाइल वास्तविक पढ़ने और लिखने प्रदर्शन करने के लिए हुक कार्यों के साथ स्थापित किया जा सकता लगते हैं। मेरे मामले में मुझे लगता है कि मैं लेखन हुक को एक लिंक्ड सूची में स्ट्रिंग की एक प्रति संलग्न करना चाहता हूं, और वहां get_string_buffer फ़ंक्शन होने के लिए जो सूची की कुल लंबाई का आंकलन करता है, इसके लिए स्मृति आवंटित करता है, और फिर प्रत्येक आइटम की प्रतिलिपि बनाता है सही जगह में इसमें।

मैं कुछ ऐसा करने का लक्ष्य रख रहा हूं जिसे do_some_stuff जैसे किसी फ़ंक्शन में पारित किया जा सके, उस फ़ंक्शन के बिना उसे FILE * प्राप्त करने के अलावा कुछ भी जानने की आवश्यकता है।

क्या इस तरह का कोई मौजूदा कार्यान्वयन है? यह एक उपयोगी और सी-अनुकूल काम करने जैसा लगता है - मान लीजिए कि मैं FILE एक्स्टेंसिबिलिटी के बारे में सही हूं।

उत्तर

5

नहीं बनाएगा तो पोर्टेबिलिटी महत्वपूर्ण नहीं है आप के लिए, आप fmemopen और open_memstream पर एक नज़र ले जा सकते हैं। वे जीएनयू एक्सटेंशन हैं, इसलिए केवल ग्लिब सिस्टम पर उपलब्ध हैं। हालांकि ऐसा लगता है कि वे POSIX.1-2008 (fmemopen और open_memstream) का हिस्सा हैं।

+0

open_memstream बिल्कुल वही है जो मैं चाहता हूं। मुझे यकीन नहीं है कि यह लिंक-सूची दृष्टिकोण का उपयोग कर रहा है, लेकिन मैं इसके लिए बड़ी मात्रा में नहीं लिखूंगा, इससे कोई फर्क नहीं पड़ता। – Edmund

2

मुझे यकीन है कि अगर यह संभव है गैर portably FILE वस्तुओं का विस्तार करने के लिए नहीं कर रहा हूँ, लेकिन आप देख रहे हैं अगर कुछ थोड़ा और अधिक POSIX अनुकूल के लिए, आप pipe और fdopen उपयोग कर सकते हैं।

यह बिल्कुल FILE* जैसा नहीं है जो बफर से बाइट देता है, लेकिन यह निश्चित रूप से FILE* प्रोग्रामेटिक रूप से निर्धारित सामग्री के साथ है।

int fd[2]; 
FILE *in_pipe; 

if (pipe(fd)) 
{ 
    /* TODO: handle error */ 
} 

in_pipe = fdopen(fd[0], "r"); 
if (!in_pipe) 
{ 
    /* TODO: handle error */ 
} 

वहां से आप write() का उपयोग कर fd[1] में अपने बफर लिखने के लिए चाहते हैं। हालांकि, इस चरण से सावधान रहें, क्योंकि write() पाइप के बफर को भरने पर रोक सकता है (यानी किसी को दूसरे छोर को पढ़ने की जरूरत है), और आपको EINTR मिल सकता है यदि आपकी प्रक्रिया लिखते समय संकेत मिलता है। SIGPIPE के लिए भी देखें, जो तब होता है जब दूसरा अंत पाइप बंद कर देता है। हो सकता है कि आपके उपयोग के लिए आप ब्लॉकिंग से बचने के लिए write बफर के अलग-अलग थ्रेड में ऐसा करना चाहें और सुनिश्चित कर लें कि आप SIGPIPE को संभाल लें।

बेशक, यह एक seekable FILE* ...

+0

+1 अच्छा के बारे में विवरण एक अलग थ्रेड की आवश्यकता – Andomar

0

मुझे यकीन नहीं है कि मैं समझता हूं कि आप FILE * के साथ गड़बड़ क्यों करना चाहते हैं। क्या आप बस एक फाइल को लिख नहीं सकते थे और फिर इसे स्ट्रिंग में लोड कर सकते थे?

char *get_file_in_buf(char *filename) { 
    char *buffer; 
    ... get file size with fseek or fstat ... 
    ... allocate buffer ... 
    ... read buffer from file ... 
    return buffer; 
} 

आप केवल एक स्ट्रिंग में स्वरूपित पाठ "लिखने" चाहते हैं, एक और विकल्प snprintf() का उपयोग कर (यह कैसे संभाल करने के लिए पर एक सुझाव के लिए इस अतः सवाल का जवाब देखने के एक विस्तृत बफर को संभालने के लिए हो सकता है: Resuming [vf]?nprintf after reaching the limit)।

, तो इसके बजाय, आप एक प्रकार है कि एक FILE * लेने उन्हें स्ट्रिंग बफ़र्स पर कार्रवाई करने के लिए किसी भी कार्य करने के लिए पारदर्शी रूप से पारित किया जा सकता बनाना चाहते हैं, यह एक और अधिक जटिल बात है ...

+0

ऐसे 'फ़ाइल *' को पाने के अच्छे कारण हैं: कई पुस्तकालय हैं जो केवल 'फ़ाइल *' आधारित I/O प्रदान करते हैं, और फ़ाइल को पढ़ने पर जोर देते हैं, जब डेटा पहले से ही स्मृति में उपलब्ध हो सकता है। इसलिए, यह पुस्तकालयों के लिए सिर्फ फाइल में लिखने के बजाय मेमोरी बफर को पारित करने में सक्षम होना वांछनीय है। दुर्भाग्यवश, इन पुस्तकालयों में शायद ही कभी, उनके 'फ़ाइल *' पर निर्भर करता है - पर निर्भर API। – greyfade

संबंधित मुद्दे