C फोपेन बनाम खुला


219

क्या कोई कारण है (सिंटैक्टिक के अलावा) जो आप उपयोग करना चाहते हैं

FILE *fdopen(int fd, const char *mode);

या

FILE *fopen(const char *path, const char *mode);

के बजाय

int open(const char *pathname, int flags, mode_t mode);

लिनक्स वातावरण में C का उपयोग करते समय?


क्या आपका मतलब है fdopenऔर openया fopenऔर open?
user7116

आप fopen मतलब नहीं है, fdopen नहीं?
सर्वव्यापी

9
fopenमानक सी लाइब्रेरी का हिस्सा है, openनहीं है। fopenपोर्टेबल कोड लिखते समय उपयोग करें ।
अज़ीज़

हां, मेरा मतलब फोपेन से था। मैंने अभी इसे अपडेट किया है, लेकिन मुझे लगता है कि यही सिद्धांत लागू होता है।
LJM

6
@ अजीज, openहालांकि एक POSIX फ़ंक्शन है।
स्वप्नदोष

जवाबों:


242

सबसे पहले, उपयोग करने के लिए कोई विशेष अच्छा कारण नहीं है fdopen यदि fopenकोई विकल्प है और openअन्य संभावित विकल्प है, तो नहीं है। openयदि आप चाहते हैं तो आपको पहली बार में फ़ाइल खोलने की आदत नहीं होनी चाहिए FILE *। तो fdopenउस सूची में शामिल करना गलत और भ्रमित करने वाला है क्योंकि यह दूसरों की तरह बहुत ज्यादा नहीं है। मैं अब इसे अनदेखा करने के लिए आगे बढ़ूंगा क्योंकि यहां महत्वपूर्ण अंतर सी मानक FILE *और एक ओएस-विशिष्ट फ़ाइल विवरणक के बीच है।

fopenइसके बजाय उपयोग करने के चार मुख्य कारण हैं open

  1. fopenआपको बफ़रिंग आईओ प्रदान करता है जो आपके द्वारा किए जा रहे कार्यों की तुलना में बहुत तेज़ हो सकते हैं open
  2. fopen यदि फ़ाइल बाइनरी मोड में नहीं खोली जाती है, तो ट्रांसलेशन एंड ट्रांसलेशन ट्रांसलेट करता है, जो आपके प्रोग्राम को कभी भी गैर-यूनिक्स वातावरण में पोर्ट करने में मददगार हो सकता है (हालाँकि दुनिया LF-only (IETF टेक्स्ट-बेस्ड नेटवर्किंग को छोड़कर) में परिवर्तित होती प्रतीत होती है SMTP और HTTP और इस तरह के प्रोटोकॉल))।
  3. FILE * आपको उपयोग करने की क्षमता fscanfऔर अन्य stdio फ़ंक्शन देता है।
  4. किसी दिन आपके कोड को किसी अन्य प्लेटफ़ॉर्म पर पोर्ट करने की आवश्यकता हो सकती है जो केवल ANSI C का समर्थन करता है और समर्थन नहीं करता है open फ़ंक्शन का है।

मेरे विचार में अनुवाद को समाप्त करने वाली पंक्ति आपकी मदद करने की तुलना में अधिक बार आपके रास्ते में आती है, और आपकी पार्सिंग fscanf इतनी कमजोर होती है कि आप अनिवार्य रूप से कुछ और उपयोगी के पक्ष में इसे समाप्त कर देते हैं।

और C का समर्थन करने वाले अधिकांश प्लेटफार्मों में ए open फ़ंक्शन है।

यह बफ़रिंग प्रश्न छोड़ देता है। उन जगहों पर जहां आप मुख्य रूप से एक फ़ाइल को क्रमिक रूप से पढ़ रहे हैं या लिख ​​रहे हैं, बफ़रिंग समर्थन वास्तव में सहायक है और एक बड़ी गति में सुधार है। लेकिन यह कुछ दिलचस्प समस्याओं को जन्म दे सकता है जिसमें डेटा फ़ाइल में समाप्त नहीं होता है जब आप इसे होने की उम्मीद करते हैं। आपको fcloseया fflushउचित समय पर याद करना होगा ।

यदि आप सीक (उर्फ fsetposया fseekजिनमें से दूसरा एक मानक अनुपालन तरीके से उपयोग करने के लिए थोड़ा पेचीदा है) कर रहे हैं, तो बफरिंग की उपयोगिता जल्दी से कम हो जाती है।

बेशक, मेरा पूर्वाग्रह यह है कि मैं पूरी तरह से सॉकेट्स के साथ काम करना चाहता हूं, और इस तथ्य को भी कि आप वास्तव में गैर-अवरुद्ध आईओ करना चाहते हैं (जो FILE *किसी भी उचित तरीके से समर्थन करने में पूरी तरह से विफल रहता है) बिना किसी बफरिंग के और अक्सर। जटिल पार्सिंग आवश्यकताएं वास्तव में मेरी धारणाओं को रंग देती हैं।


4
मैं आपके अनुभवों पर सवाल नहीं उठा रहा हूं, लेकिन मैं आपको इस बारे में थोड़ा विस्तार से सुनना पसंद करूंगा। किस तरह के अनुप्रयोगों के लिए आपको लगता है कि अंतर्निहित बफ़रिंग रास्ते में मिलती है? वास्तव में समस्या क्या है?
एमिल एच

1
अंतिम पैराग्राफ नहीं देखा। मान्य बिंदु, IMHO। जहाँ तक मैं बता सकता हूँ कि प्रश्न फ़ाइल IO के बारे में था, हालाँकि।
एमिल एच

7
जब बफरिंग रास्ते में हो जाता है स्पष्ट करने के लिए। यह तब होता है जब आप तलाश करते हैं। जो कुछ भी आदेश के साथ निम्न पढ़ने ( fgets, fgetc, fscanf, fread), हमेशा बफर (4K, 8K या जो भी आप सेट) के पूर्ण आकार का पढ़ा जाएगा। प्रत्यक्ष I / O का उपयोग करके आप इससे बच सकते हैं। उस मामले में यह preadएक तलाश / पढ़ने की जोड़ी (2 के बजाय 1 syscall) के बजाय उपयोग करना बेहतर है ।
पैट्रिक श्ल्टर

2
रुकावट read()और write()कॉल को संभालना कार्यों के लिबास परिवार का उपयोग करने का एक सुविधाजनक पांचवा कारण है।
nccc

3
@ m-ric: खैर, यह कुछ हद तक असंबंधित प्रश्न है, लेकिन हाँ। समर्थन करने वाले सभी प्लेटफ़ॉर्म ioctlभी filenoकॉल का समर्थन करते हैं जो FILE *एक नंबर लेता है और एक नंबर देता है जिसका उपयोग ioctlकॉल में किया जा सकता है । हालांकि सावधान रहें। FILE *संबंधित कॉल ioctlअंतर्निहित फ़ाइल डिस्क्रिप्टर के बारे में कुछ बदलने के लिए आश्चर्यजनक रूप से बातचीत कर सकते हैं ।
सर्वव्यापी

53

open()एक निम्न-स्तरीय ओएस कॉल है। fdopen()C भाषा के उच्च-स्तरीय FILE-abstraction के लिए os-level फ़ाइल डिस्क्रिप्टर को कनवर्ट करता है।fopen()open()पृष्ठभूमि में कॉल करता है और आपको सीधे एक फ़ाइल-पॉइंटर देता है।

फ़ाइल-ऑब्जेक्ट के बजाय कच्चे फ़ाइल डिस्क्रिप्टर का उपयोग करने के कई फायदे हैं, जिसमें उपयोग में अधिक आसानी लेकिन अन्य तकनीकी फायदे भी शामिल हैं जैसे अंतर्निहित बफ़रिंग। विशेष रूप से बफ़रिंग आमतौर पर बड़े पैमाने पर प्रदर्शन लाभ का परिणाम है।


3
क्या खुले के बफ़र किए गए 'f ...' वर्जन का उपयोग करने के कोई नुकसान हैं?
LJM

5
@L। मोजर, हां, जब आप पहले से ही डेटा को बफर कर रहे हैं, और इसलिए अतिरिक्त बफर अनावश्यक नकल और मेमोरी ओवरहेड जोड़ता है।
बजे माइकल आरोन सफायन

6
वास्तव में अन्य नुकसान भी हैं। fopen()फ़ाइलें खोलते समय समान स्तर का नियंत्रण प्रदान नहीं करता है, उदाहरण के लिए अनुमतियाँ, साझाकरण मोड और बहुत कुछ। आमतौर पर open()और वेरिएंट बहुत अधिक नियंत्रण प्रदान करते हैं, ऑपरेटिंग सिस्टम वास्तव में क्या प्रदान करता है
मैट जॉइनर

2
चरम मामले भी हैं जहां आप mmapफ़ाइल करते हैं और सामान्य I / O के साथ परिवर्तन करते हैं (जैसा कि अविश्वसनीय लगता है कि हम वास्तव में हमारे प्रोजेक्ट में और वास्तविक अच्छे कारणों से करते हैं), बफरिंग रास्ते में होगी।
पैट्रिक श्ल्टर

आप अन्य सिस्टम फ़ंक्शंस का उपयोग करना चाह सकते हैं, जैसे कि रीडाहेड () के माध्यम से पेज कैश में फ़ाइलों को प्रीलोड करने के लिए ओपन () का उपयोग करना। मुझे लगता है कि अंगूठे का नियम है "फोपेन का उपयोग करें जब तक कि आपको पूरी तरह से खुले ()" की आवश्यकता न हो, खुला () वास्तव में आपको फैंसी सामान (सेटिंग O_ATIME और इसी तरह की सेटिंग नहीं / स्थापित) करने देता है।
टॉमस प्रुजिना

34

फोपेन बनाम सी में खुला

1) fopenएक लाइब्रेरी फंक्शन है जबकि openएक सिस्टम कॉल है

2) बफर आइओfopen प्रदान करता है जो तेजी से तुलना की जाती है जो गैर बफर हैopen

3) fopenहै पोर्टेबल जबकि openनहीं पोर्टेबल ( खुला माहौल विशिष्ट है )।

4) fopenएक FILE संरचना (FILE *) के लिए एक पॉइंटर लौटाता है ; openएक पूर्णांक देता है जो फ़ाइल की पहचान करता है।

5) A FILE *आपको fscanf और अन्य stdio फ़ंक्शन का उपयोग करने की क्षमता देता है ।


9
openPOSIX मानक है, इसलिए यह काफी पोर्टेबल है
osvein

12

जब तक आप 0.1% अनुप्रयोगों का हिस्सा नहीं होते हैं, जहां उपयोग openकरना एक वास्तविक प्रदर्शन लाभ है, वास्तव में उपयोग न करने का कोई अच्छा कारण नहीं है fopen। जहाँ तक fdopenबात है, यदि आप फ़ाइल डिस्क्रिप्टर के साथ नहीं खेल रहे हैं, तो आपको उस कॉल की आवश्यकता नहीं है।

साथ छड़ी fopenऔर तरीकों के अपने परिवार ( fwrite, fread, fprintf, एट अल) और तुम बहुत संतुष्ट हो जाएगा। महत्वपूर्ण रूप से, अन्य प्रोग्रामर आपके कोड से संतुष्ट होंगे।


11

यदि आप एक है, तो FILE *, आप जैसे कार्यों का उपयोग कर सकते fscanf, fprintfऔर fgetsआदि तुम सिर्फ फ़ाइल वर्णनकर्ता है, तो आप सीमित है (लेकिन संभावना तेज) इनपुट और आउटपुट दिनचर्या read, writeआदि


7

ओपन, रीड, राइट का उपयोग करने का मतलब है कि आपको सिग्नल इंटरप्टेशन के बारे में चिंता करनी होगी।

यदि सिग्नल सिग्नल हैंडलर द्वारा कॉल को बाधित किया गया था, तो फ़ंक्शन -1 वापस आ जाएगा और EINTR को गलत सेट करेगा।

तो एक फ़ाइल को बंद करने का उचित तरीका होगा

while (retval = close(fd), retval == -1 && ernno == EINTR) ;

4
इसके लिए close, यह ऑपरेटिंग सिस्टम पर निर्भर करता है। लिनक्स, AIX और कुछ अन्य ऑपरेटिंग सिस्टम पर लूप करना गलत है।
स्ट्रेट डे

इसके अलावा, पढ़ने और लिखने का उपयोग करने से एक ही समस्या का सामना करना पड़ेगा, अर्थात, इनपुट / आउटपुट को पूरी तरह से संसाधित करने से पहले वे सिग्नल से बाधित हो सकते हैं और प्रोग्रामर को ऐसी स्थितियों को संभालना पड़ता है, जबकि फ़्रेड और राइटराइट सिग्नल सिग्नल को अच्छी तरह से हैंडल करते हैं।
मार्सेलो

6

open()यूनिक्स-आधारित सिस्टम के लिए एक सिस्टम कॉल और विशिष्ट है और यह एक फाइल डिस्क्रिप्टर लौटाता है। आप एक फाइल डिस्क्रिप्टर पर लिख सकते हैं write()जिसका उपयोग करके एक और सिस्टम कॉल किया जाता है।
fopen()एक एएनएसआई सी फ़ंक्शन कॉल है जो एक फाइल पॉइंटर लौटाता है और यह अन्य ओएस के लिए पोर्टेबल है। हम एक फ़ाइल पॉइंटर का उपयोग करके लिख सकते हैंfprintf

यूनिक्स में:
आप फ़ाइल डिस्क्रिप्टर का उपयोग करके एक फ़ाइल पॉइंटर प्राप्त कर सकते हैं:

fP = fdopen(fD, "a");

आप फ़ाइल पॉइंटर से फाइल डिस्क्रिप्टर का उपयोग करके प्राप्त कर सकते हैं:

fD = fileno (fP);

4

खुले () को फोपेन () पारिवारिक कार्यों में से प्रत्येक के अंत में बुलाया जाएगा । ओपन () एक सिस्टम कॉल है और फ़ोपेन () पुस्तकालयों द्वारा उपयोग में आसान उपयोगकर्ता के लिए एक आवरण कार्यों के रूप में प्रदान किया जाता है


2

मैंने अपने आवेदन के लिए () फोपेन () से ओपन () में बदलाव किया, क्योंकि फोपेन हर बार जब मैं फोपेन फेटेक को चलाता था, तो डबल रीड पढ़ रहा था। डबल रीड्स इस बात से खफा थे कि मैं क्या हासिल करना चाह रहा था। खुला () बस वही करने लगता है जो आप उससे पूछते हैं।


2

यह भी निर्भर करता है कि किन झंडों को खोलना आवश्यक है। लेखन और पढ़ने के लिए उपयोग के संबंध में (और पोर्टेबिलिटी) च * का उपयोग किया जाना चाहिए, जैसा कि ऊपर तर्क दिया गया है।

लेकिन अगर मूल रूप से मानक झंडे (जैसे आरडब्ल्यू और एपेंड झंडे) से अधिक निर्दिष्ट करना चाहते हैं, तो आपको एक मंच विशिष्ट एपीआई (जैसे पोसिक्स खुला) या इन विवरणों को सार करने वाले पुस्तकालय का उपयोग करना होगा। सी-स्टैंडर्ड में ऐसे कोई झंडे नहीं हैं।

उदाहरण के लिए, आप किसी फ़ाइल को खोलना चाहते हैं, केवल तभी जब वह बाहर निकले। यदि आप बनाएँ ध्वज को निर्दिष्ट नहीं करते हैं तो फ़ाइल मौजूद होनी चाहिए। यदि आप बनाने के लिए अनन्य जोड़ते हैं, तो यह केवल फ़ाइल बनाएगा यदि यह मौजूद नहीं है। और भी कई हैं।

लिनक्स सिस्टम पर उदाहरण के लिए एक एलईडी इंटरफ़ेस है जो sysfs के माध्यम से उजागर होता है। यह एक फ़ाइल के माध्यम से एलईडी की चमक को उजागर करता है। 0-255 से लेकर एक स्ट्रिंग के रूप में एक संख्या लिखना या पढ़ना। बेशक आप उस फ़ाइल को बनाना नहीं चाहते हैं और यदि मौजूद है तो ही उसे लिखें। अब ठंडी बात: मानक कॉल का उपयोग करके इस फ़ाइल को पढ़ने / लिखने के लिए fdopen का उपयोग करें।


0

एक फ़ाइल को खोलने का उपयोग fopen
इससे पहले कि हम पढ़ (या लिख) (करने के लिए) एक डिस्क हम फ़ाइल को खोलने चाहिए पर एक फ़ाइल से जानकारी कर सकते हैं। फ़ाइल खोलने के लिए हमने फंक्शन को फोपेन कहा है।

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

यह fopen फ़ंक्शन के व्यवहार का तरीका है
बफ़रिंग प्रक्रिया के दौरान कुछ कारण हैं, यह समयबद्ध हो सकता है। इसलिए फोपेन (उच्च स्तर i / o) को खोलने के लिए (निम्न स्तर i / o) सिस्टम कॉल की तुलना करते समय , और यह fopen की तुलना में अधिक तेज़ है ।


फोपेन की तुलना में तेजी से खुला है?
ओबायहान

हां, ओपन सिस्टम कॉल है, जो कि फोपेन से तेज है - तुलनात्मक रूप से @obayhan
prashad
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.