2013-02-14 51 views
5

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

#include <stdio.h> 
int main() 
{ 
    FILE * fp = fopen("test.txt", "r+"); 
    char line[100] = {'\0'}; 
    int count = 0; 
    int ret_code = 0; 
    while(!feof(fp)){ 
     fgets(line, 100, fp); 
     // do some processing on line... 
     count++; 
     if(count == 4) { 
      ret_code = fprintf(fp, "replaced this line\n"); 
      printf("ret code was %d\n", ret_code); 
      perror("Error was: "); 
     } 
    } 
    fclose(fp); 
    return 0; 
} 

अब लिनक्स पर, जीसीसी (4.6.2) इस कोड को चलाता है के साथ संकलित, और फ़ाइल की 5 वीं लाइन संशोधित करता है। विजुअल सी ++ 2010 रनों के साथ संकलित विंडोज 7 पर चलने वाला एक ही कोड और सफल होने का दावा (रिपोर्ट 1 9 वर्णों और perror का रिटर्न कोड "कोई त्रुटि नहीं" कहता है) लेकिन लाइन को प्रतिस्थापित करने में विफल रहता है।

लिनक्स पर मेरी फाइल है पूर्ण अनुमति:

-rw-rw-rw- 1 mike users 191 Feb 14 10:11 test.txt 

और विंडोज पर एक ही जहाँ तक मैं यह मिल सकती है:

test.txt (राइट क्लिक) -> गुण -> सुरक्षा
"अनुमति दें" को & पढ़ने के लिए चेक किया गया है उपयोगकर्ता, सिस्टम और व्यवस्थापक के लिए लिखें।

मुझे विंडोज़ पर मिनजीडब्ल्यू के जीसीसी का उपयोग करके एक ही परिणाम मिलते हैं, इसलिए मुझे पता है कि यह विज़ुअल सी ++ "फीचर" नहीं है।

क्या मुझे कुछ स्पष्ट याद आ रही है, या यह तथ्य है कि मुझे कोई त्रुटि नहीं है, लेकिन r+ का उपयोग करने के लिए विंडोज़ पर fopen() का उपयोग करने के लिए केवल एक अनियंत्रित "फीचर" नहीं है?


संपादित करें:
लगता है यहां तक ​​कि Microsoft's site पर वे कहते हैं कि "r +" पढ़ने और writting के लिए खोल देना चाहिए। उन्होंने यह नोट भी बनाया:

जब "आर +", "डब्ल्यू +", या "ए +" एक्सेस प्रकार निर्दिष्ट किया गया है, तो दोनों पढ़ने और लिखने की अनुमति है (फ़ाइल को "अपडेट" के लिए खुला कहा जाता है) । हालांकि, जब आप पढ़ने और लिखने के बीच स्विच करते हैं, तो एक हस्तक्षेप Fflush, fsetpos, fseek, या रिवाइंड ऑपरेशन होना चाहिए। वांछित अगर वर्तमान स्थिति fsetpos या fseek ऑपरेशन के लिए निर्दिष्ट किया जा सकता है।

तो मैं करने की कोशिश की:

 ... 
     if(count == 4) { 
      fflush(fp); 
      ret_code = fprintf(fp, "replaced this line\n"); 
      fflush(fp); 
      printf("ret code was %d\n", ret_code); 
      ... 

कोई लाभ नहीं हुआ।

+0

क्या आपने लिखने के ऑपरेशन के बाद 'fflush' का उपयोग करके स्ट्रीम को फ़्लश करने का प्रयास किया है? – Cyclonecode

+3

मुझे यकीन नहीं है कि यह समस्या है, लेकिन फ़ाइल – Hasturkun

+0

@KristerAndersson - yup से पढ़ने और लिखने के बीच स्विच करते समय आपको 'fseek' को कॉल करने की आवश्यकता हो सकती है, बस यह स्पष्ट करने के लिए अपडेट किया गया कि मैंने एमएसडीएन साइट पर नोट देखा जो आपको बताता है स्ट्रीम को 'एफ ()' में से एक द्वारा अपडेट करना चाहिए, इसलिए मैंने लिखने से पहले और बाद में 'fflush() 'ing की कोशिश की, लेकिन कोई पासा नहीं। – Mike

उत्तर

3

Linux man page for fopen() के अनुसार:

रीड और राईट किसी भी क्रम में पढ़ें/लिखें धाराओं पर intermixed जा सकता है। ध्यान दें कि एएनएसआई सी की आवश्यकता है कि एक फ़ाइल पोजीशनिंग फ़ंक्शन आउटपुट और इनपुट के बीच हस्तक्षेप करे, जब तक कोई इनपुट ऑपरेशन अंत-फ़ाइल का सामना न करे। (यदि यह स्थिति पूरी नहीं हुई है, तो को पढ़ने के लिए सबसे हालिया के अलावा अन्य लेखों को पढ़ने की अनुमति है।) इसलिए को एक fseek (3) डालने के लिए अच्छी प्रैक्टिस (और वास्तव में कभी-कभी लिनक्स के तहत आवश्यक) है। fgetpos (3) इस तरह की धारा पर लिखने और पढ़ने के संचालन के बीच ऑपरेशन। इस आपरेशन fseek (..., 0L, SEEK_CUR) ने अपने सिंक्रनाइज़ करना पक्ष प्रभाव के लिए कहा जाता है के रूप में एक स्पष्ट नहीं सेशन (हो सकता है।

तो, आप हमेशा fseek() बुलाना चाहिए (के रूप में, उदाहरण के लिए।fseek(..., 0, SEEK_CUR)) फ़ाइल से पढ़ने और लिखने के बीच स्विच करते समय।

+1

यह समस्या थी, और यही वह है जो मुझे मैन पेज के बजाय एमएसडीएन दस्तावेज पढ़ने के लिए मिलता है। :) धन्यवाद। – Mike

+0

ध्यान दें कि एमएसडीएन (वीएस 2012 के लिए) के सबसे हालिया दस्तावेज़ अपडेट किए गए हैं: http://msdn.microsoft.com/en-us/library/yeby3zcb.aspx –

+0

@MichaelBurr - अच्छा बिंदु, जो सबसे अधिक नहीं था हालिया दस्तावेज, मुझे अपना बुकमार्क अपडेट करना चाहिए, थोड़ी देर के बाद से मैं वहां गया हूं। – Mike

3

इनपुट के बाद आउटपुट करने से पहले, fflush() कोई अच्छा नहीं है - आपको एक तलाश ऑपरेशन करने की आवश्यकता है। कुछ की तरह:

fseek(fp, ftell(fp), SEEK_SET); // not fflush(fp); 
C99 मानक से

(7.19.5.3/6 "fopen functoin):

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

+0

यह मजाकिया है, आप कहते हैं कि "fflush() कोई अच्छा नहीं है" लेकिन फिर आपके द्वारा उद्धृत सी 99 स्निपेट कहता है: 'fflush फ़ंक्शन में एक हस्तक्षेप कॉल के बिना या फ़ाइल पोजीशनिंग फ़ंक्शन' के बिना। तो, ठीक है, यह कहता है कि 'fflush() 'या' fseek()'/अन्य पोजिशनिंग फ़ंक्शंस। – Mike

+2

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

+0

+1 इसे मिला, यह आदेश देता है कि आदेश क्यों मायने रखता है। उस इनपुट के लिए धन्यवाद। – Mike