फ़र्ज़ी / फ़ेराईट को आकार लेने और तर्क के रूप में गिनने के लिए तर्क क्या है?


96

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

से fread (3) :

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

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

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


10
हे यह एक अच्छा सवाल है। मैं हमेशा इसके बारे में सोचता था
जोहान्स शहाब -

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

जवाबों:


22

यह इस बात पर आधारित है कि कैसे भय को लागू किया जाता है।

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

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

fgetc में यह नोट भी है:

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

बेशक, यह UTF-8 की तरह फैंसी चर-बाइट चरित्र एन्कोडिंग से पहले है।

SUS नोट करता है कि यह वास्तव में ISO C दस्तावेजों से लिया गया है।


72

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


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

3
यदि औचित्य पूरा हो जाता तो यह बहुत अच्छा जवाब देता।
मैट जॉइनर

13

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

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


1
मुझे खुशी है कि किसी ने इसे लाया। मैंने फाइलसिस्टम स्पेक्स और एफटीपी और रिकॉर्ड्स / पेज के साथ बहुत काम किया और अन्य ब्लॉकिंग कॉन्सेप्ट्स को बहुत मजबूती से सपोर्ट किया जाता है, हालांकि कोई भी स्पेक्स के उन हिस्सों का इस्तेमाल नहीं करता है।
मैट जॉइनर

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(), मैं बहुत पहले ही अनुमान लगा सकता हूं इसलिए मैंने K & R की अपनी प्रति खो दी है। मुझे लगता है कि एक संभावित उत्तर यह है कि कार्निघन और रिची ने केवल यह सोचा होगा कि द्विआधारी I / O प्रदर्शन करना स्वाभाविक रूप से वस्तुओं के सरणियों पर किया जाएगा। इसके अलावा, उन्होंने सोचा हो सकता है कि कुछ आर्किटेक्चर पर या कुछ भी लागू करने के लिए ब्लॉक I / O अधिक तेज़ / आसान होगा।

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

अंत में, यहाँ PJ प्लॉजर का fread()"द स्टैंडर्ड सी लाइब्रेरी" के बारे में क्या कहना है :

यदि size(दूसरा) तर्क एक से अधिक है, तो आप यह निर्धारित नहीं कर सकते हैं कि फ़ंक्शन size - 1क्या रिपोर्ट करता है इससे परे अतिरिक्त वर्णों को भी पढ़ें । एक नियम के रूप में, आप fread(buf, 1, size * n, stream);इसके बजाय फ़ंक्शन को कॉल करने से बेहतर हैंfread(buf, size, n, stream);

मूल रूप से, वह कह रहा है कि fread()इंटरफ़ेस टूट गया है। के लिए fwrite()उनका यह भी कहना है कि, "लिखें त्रुटियों, आम तौर पर दुर्लभ हैं तो यह एक प्रमुख कमी नहीं है" - एक बयान मैं सहमत नहीं होता।


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

1
@ आर .. बस उस आकार की जाँच करना सुनिश्चित करें *! = 0 के अलावा! फ़्रेड (...)। यदि आकार * गिनती == 0, आपको एक सफल रीड (शून्य बाइट्स) पर शून्य रिटर्न मान मिल रहा है , तो फ़ॉफ़ () और फ़ेरोर () सेट नहीं किया जाएगा, और इरानो एनोएंट की तरह कुछ निरर्थक होगा, या इससे भी बदतर EAGAIN की तरह कुछ भ्रामक (और संभवतः गंभीर रूप से टूटने वाला) - बहुत भ्रामक, विशेष रूप से मूल रूप से कोई प्रलेखन इस गॉच को आप पर चिल्लाता है।
पेगासस एप्सिलॉन

3

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


ज़रुरी नहीं। Fwrite नोटों के लिए C विनिर्देश जो इसे बार-बार कॉल करता है fputc: opengroup.org/onlinepubs/009695399/functions/fwrite.html
Powerlord

1

आकार और गणना के लिए अलग-अलग तर्क रखने से कार्यान्वयन पर फायदा हो सकता है जो किसी भी आंशिक रिकॉर्ड को पढ़ने से बच सकते हैं। यदि किसी को पाइप से किसी चीज की तरह सिंगल-बाइट रीड्स का उपयोग करना होता है, भले ही कोई फिक्स्ड-फॉर्मेट डेटा का उपयोग कर रहा हो, तो किसी को रिकॉर्ड को दो रीड्स में विभाजित होने की संभावना के लिए अनुमति देना होगा। यदि इसके बजाय अनुरोध हो सकता है जैसे 103 बाइट्स के 40 रिकॉर्ड तक गैर-अवरुद्ध रीडिंग जब प्रत्येक में 293 बाइट्स उपलब्ध हों, और सिस्टम में 290 बाइट्स (29 पूरे रिकॉर्ड) लौटें, जबकि अगले रीड के लिए 3 बाइट्स तैयार हों, और अधिक सुविधाजनक हो।

मुझे नहीं पता कि इस तरह के शब्दार्थ को किस हद तक कार्यान्वित किया जा सकता है, लेकिन वे उन कार्यान्वयनों पर निश्चित रूप से काम कर सकते हैं जो उनका समर्थन करने का वादा कर सकते हैं।


@PegasusEpsilon: यदि कोई प्रोग्राम करता है fread(buffer, 10000, 2, stdin)और उपयोगकर्ता 18,000 बाइट टाइप करने के बाद newline-ctrl-D टाइप करता है, तो यह अच्छा होगा यदि फ़ंक्शन पहले 10,000 बाइट्स वापस कर सकता है, जबकि शेष 8,000 भविष्य के छोटे पढ़ने के अनुरोधों के लिए लंबित हैं, लेकिन हैं किसी भी कार्यान्वयन जहां यह होगा? उन भावी अनुरोधों को लंबित रखते हुए 8,000 बाइट कहाँ संग्रहीत किए जाएंगे?
सुपरकैट

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

... जारी रखा ... सबसे अच्छा आप कर सकते हैं शायद अपने रीड बफर को फ़्रेड से पहले नल के साथ भरें, और रिकॉर्ड की जांच करें जहां फ़्रेड () के बाद यह किसी भी गैर-शून्य बाइट्स के लिए समाप्त हो गया है। आपके रिकॉर्ड के अशक्त होने पर विशेष रूप से आपकी मदद नहीं करता है, लेकिन यदि आप size1 से अधिक का उपयोग करने जा रहे हैं , तो ठीक है ... रिकॉर्ड के लिए, इसमें ioctls या अन्य बकवास भी हो सकते हैं जिन्हें आप इसे बनाने के लिए स्ट्रीम पर लागू कर सकते हैं अलग तरह से व्यवहार करें, मैंने उस पर गहराई से ध्यान नहीं दिया।
पेगासस एप्सिलॉन

इसके अलावा, मैंने अशुद्धि के कारण अपनी पिछली टिप्पणी हटा दी है। ओह अच्छा।
पेगासस एप्सिलॉन

@PegasusEpsilon: C का उपयोग कई प्लेटफार्मों पर किया जाता है, जो विभिन्न व्यवहारों को समायोजित करते हैं। यह धारणा कि प्रोग्रामर को सभी कार्यान्वयनों पर समान सुविधाओं और गारंटियों का उपयोग करने की अपेक्षा करनी चाहिए, सी की सबसे अच्छी विशेषता थी, इस बात की अनदेखी करते हैं: कि इसका डिज़ाइन प्रोग्रामर को उन प्लेटफार्मों पर सुविधाओं और गारंटियों का उपयोग करने की अनुमति देगा जहां वे उपलब्ध थे। कुछ प्रकार की धाराएं मनमाने ढंग से आकार की पुशबैक का आसानी से समर्थन कर सकती हैं, और freadआपके द्वारा इस तरह की धाराओं पर वर्णित कार्य उपयोगी होंगे यदि उन तरीकों को पहचानने के लिए कुछ तरीके हैं जो उस फैशन में काम करते हैं।
सुपरकैट

0

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

इस पर विचार करो:

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

यदि बाइट्स की स्वीकृत संख्या को फिर से लिखा जाए, तो आप निम्नलिखित लिख सकते हैं:

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

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

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

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

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