2008-11-17 13 views
74

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

fread (3) से:

समारोह fread() डेटा के nmemb तत्वों पढ़ता है, प्रत्येक आकार बाइट्स लंबे, धारा से धारा के द्वारा की ओर इशारा किया, उन्हें दिए गए स्थान पर भंडारण पीटीआर द्वारा

समारोह fwrite() डेटा के nmemb तत्वों, प्रत्येक आकार बाइट्स लिखते हैं लंबे, करने के लिए धारा धारा के द्वारा की ओर इशारा किया, उन्हें स्थान ptr द्वारा दिए गए से प्राप्त करने के।

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

+9

हे यह एक अच्छा सवाल है। मैं हमेशा इसके बारे में सोचता हूं –

+1

कृपया इस धागे को देखें: http://stackoverflow.com/questions/8589425/how-does-fread-really-work – Franken

उत्तर

18

यह इस पर आधारित है कि कैसे fread लागू किया गया है।

एकल यूनिक्स विशिष्टता का कहना है

प्रत्येक वस्तु के लिए, आकार कॉल fgetc() फ़ंक्शन करने के लिए, में अहस्ताक्षरित चार की एक सरणी वास्तव में किया जाएगा और परिणाम संग्रहीत, पढ़ने के क्रम में ऑब्जेक्ट को ओवरलेइंग ।

fgetc भी इस नोट है:

fgetc के बाद से

() बाइट्स पर चल रही है, कई बाइट्स (या "एक बहु बाइट चरित्र") से मिलकर एक चरित्र कई कॉल की आवश्यकता हो सकती पढ़ने fgetc() में।

बेशक, यह यूटीएफ -8 जैसे फैंसी चर-बाइट वर्ण एन्कोडिंग की भविष्यवाणी करता है।

एसयूएस नोट करता है कि यह वास्तव में आईएसओ सी दस्तावेजों से लिया जाता है।

50

fread में अंतर (buf, 1000, 1, धारा) और fread (buf, 1, 1000, धारा), है कि पहले मामले में आप अगर, 1000 बाइट्स या nuthin का केवल एक हिस्सा मिलता है फ़ाइल छोटी है और दूसरे मामले में आपको फ़ाइल में सब कुछ 1000 बाइट से कम और कम मिलता है।

+3

हालांकि सच है, जो केवल कहानी का एक छोटा सा हिस्सा बताता है। कुछ पढ़ने, कहने, int मूल्यों की एक सरणी, या संरचनाओं की एक सरणी को विपरीत करना बेहतर होगा। –

+2

औचित्य पूरा होने पर यह एक अच्छा जवाब देगा। –

+0

व्यावहारिक उत्तर। धन्यवाद – austin

3

संभावना है कि यह फ़ाइल I/O लागू करने के तरीके पर वापस आ जाए। (दिन में वापस) ब्लॉक में फ़ाइलों को लिखने/पढ़ने के लिए तेज़ी से सब कुछ लिखने के लिए तेज़ी से हो सकता है।

+0

वास्तव में नहीं। Fwrite के लिए सी विनिर्देश नोट करता है कि यह fputc को बार-बार कॉल करता है: http://www.opengroup.org/onlinepubs/009695399/functions/fwrite.html – Powerlord

9

यहाँ, मुझे उन कार्यों को ठीक करते हैं:

size_t fread_buf(void* ptr, size_t size, FILE* stream) 
{ 
    return fread(ptr, 1, size, stream); 
} 


size_t fwrite_buf(void const* ptr, size_t size, FILE* stream) 
{ 
    return fwrite(ptr, 1, size, stream); 
} 

fread()/fwrite() के मापदंडों के लिए एक तर्क के रूप में, मैं बहुत पहले कश्मीर & आर के मेरी प्रतिलिपि खो दिया है तो मैं केवल अनुमान लगा सकते हैं। मुझे लगता है कि एक संभावित उत्तर यह है कि केर्निगन और रिची ने शायद सोचा होगा कि बाइनरी I/O निष्पादित करना ऑब्जेक्ट्स के सरणी पर सबसे स्वाभाविक रूप से किया जाएगा। साथ ही, उन्होंने सोचा होगा कि ब्लॉक I/O लागू करने के लिए तेज़/आसान होगा या कुछ आर्किटेक्चर पर जो भी हो।

हालांकि सी मानक निर्दिष्ट करता है कि fread() और fwrite()fgetc() और fputc() के मामले में लागू किया जाना, याद रखें कि मानक लंबे समय के बाद सी कश्मीर & R से और मानक में निर्दिष्ट बातें नहीं हो सकता है कि परिभाषित किया गया था अस्तित्व में आया मूल डिजाइनरों के विचारों में। यह भी संभव है कि के & आर में "सी प्रोग्रामिंग भाषा" में कहा गया हो सकता है कि भाषा पहली बार डिज़ाइन की गई थी।

अंत में, यहाँ क्या पी.जे. Plauger "मानक सी लाइब्रेरी" में fread() के बारे में क्या कहना है है: चाहे समारोह भी पढ़

तो size (दूसरा) तर्क एक से अधिक है, तो आप निर्धारित नहीं कर सकता size - 1 तक जो कुछ भी रिपोर्ट करता है उससे परे अतिरिक्त वर्ण। एक नियम के रूप में, आप के बजाय fread(buf, size, n, stream);

fread(buf, 1, size * n, stream); के रूप में फ़ंक्शन को कॉल Bascially से बेहतर कर रहे हैं, वह कह रहा है कि fread() के इंटरफेस टूटी हुई है। fwrite() के लिए उन्होंने नोट किया कि, "लिखें त्रुटियां आम तौर पर दुर्लभ होती हैं, इसलिए यह एक बड़ी कमी नहीं है" - एक बयान जो मैं सहमत नहीं हूं।

+16

दरअसल मैं अक्सर इसे अन्य तरीके से करना पसंद करता हूं: 'fread (buf, आकार * एन, 1, स्ट्रीम); 'अगर अधूरा पढ़ना एक त्रुटि स्थिति है, तो पढ़ने के बाइट्स की संख्या के बजाय 0 या 1 को वापस करने के लिए' फ्रेड' 'की व्यवस्था करना आसान है। फिर आप बाइट्स के अनुरोधित संख्या (जिसके लिए अतिरिक्त सी कोड और अतिरिक्त मशीन कोड की आवश्यकता होती है) के मुकाबले परिणाम की तुलना करने के बजाय 'if (! Fread (...)) जैसी चीजें कर सकते हैं। –

12

यह शुद्ध अटकलें हैं, हालांकि दिनों में वापस (कुछ अभी भी आसपास हैं) कई फाइल सिस्टम हार्ड ड्राइव पर सरल बाइट स्ट्रीम नहीं थे।

कई फाइल सिस्टम रिकॉर्ड आधारित थे, इस प्रकार इस तरह के फाइल सिस्टम को कुशल तरीके से संतुष्ट करने के लिए, आपको वस्तुओं की संख्या ("रिकॉर्ड्स") निर्दिष्ट करना होगा, जिससे रिकॉर्ड के रूप में भंडारण पर संचालित करने के लिए fwrite/fread को अनुमति नहीं दी जाएगी, न कि बस बाइट स्ट्रीम।

+1

मुझे खुशी है कि कोई इसे लाया है। मैंने फाइल सिस्टम चश्मे और एफ़टीपी के साथ बहुत सारे काम किए और रिकॉर्ड/पेज और अन्य अवरोध अवधारणाएं बहुत दृढ़ता से समर्थित हैं, हालांकि कोई भी चश्मे के उन हिस्सों का उपयोग नहीं करता है। –

1

मुझे लगता है कि ऐसा इसलिए है क्योंकि सी में कार्य ओवरलोडिंग की कमी है। अगर कुछ था, तो आकार अनावश्यक होगा। लेकिन सी में आप एक सरणी तत्व का आकार निर्धारित नहीं कर सकते हैं, आपको एक निर्दिष्ट करना होगा।

पर विचार करें:

int intArray[10]; 
fwrite(intArray, sizeof(int), 10, fd); 

बाइट्स की fwrite स्वीकार कर लिया संख्या, तो आपको निम्न लिख सकता है:

int intArray[10]; 
fwrite(intArray, sizeof(int)*10, fd); 

लेकिन यह सिर्फ अक्षम है। आपके पास आकार (int) बार अधिक सिस्टम कॉल होंगे।

एक और बिंदु जिसे ध्यान में रखा जाना चाहिए यह है कि आप आमतौर पर किसी फ़ाइल में किसी सरणी तत्व के हिस्से को नहीं लिखना चाहते हैं। आप पूरे पूर्णांक या कुछ भी नहीं चाहते हैं। fwrite सफलतापूर्वक लिखे गए कई तत्व लौटाता है। तो यदि आप पाते हैं कि तत्व के केवल 2 कम बाइट लिखे गए हैं तो आप क्या करेंगे?

कुछ सिस्टम (संरेखण के कारण) पर आप एक प्रतिलिपि बनाने और प्रतिलिपि बनाने के बिना पूर्णांक के एक बाइट तक नहीं पहुंच सकते हैं।

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