2013-02-14 34 views
5

我正在打開一些正在打開,閱讀和修改文本文件的代碼。快速(簡體)的例子是:使用「r +」在fopen上windows vs linux

#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; 
} 

現在在Linux上,與海灣合作委員會(4.6.2)運行此代碼編譯,並修改文件的5日線。使用Visual C++ 2010編譯的Windows7上運行的相同代碼運行並聲稱已成功(報告返回碼爲19個字符,而perror表示「無錯誤」),但未能替換該行。

在Linux上我的文件具有完全的權限:

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

而據我可以告訴它是相同的Windows:

的test.txt(右鍵) - >屬性 - >安全
檢查「允許」爲讀取&寫入用戶,系統和管理員。

我在Windows上使用MinGW的gcc獲得了相同的結果,所以我知道它不是一個Visual C++「功能」。

我失去了一些東西明顯,或者是我沒有得到任何錯誤的情況,也沒有輸出只使用r+fopen()在Windows上的無證「功能」?


編輯:
似乎即使在Microsoft's site他們說 「R +」 應該打開閱讀書面方式。他們還提出了這樣一個字條:

當「R +」,「W +」,或「+」訪問類型指定,閱讀和寫作都被允許(該文件被認爲是開放的「更新」) 。但是,當您在讀取和寫入之間切換時,必須存在干預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 2013-02-14 15:47:36

+3

我不確定這是否是問題,但您可能需要在文件 – Hasturkun 2013-02-14 15:48:47

+0

@KristerAndersson - yup之間切換讀取和寫入時調用'fseek',只是更新以澄清我在MSDN網站上看到說你的註釋應該更新'f ()'之一的流,所以我在寫入之前和之後嘗試了'fflush()',但沒有骰子。 – Mike 2013-02-14 15:51:46

回答

3

按照Linux man page for fopen()

讀取和寫入可被以任何順序的讀/寫數據流混合。 請注意,ANSI C要求文件定位功能在輸出和輸入之間插入 ,除非輸入操作遇到 文件結束。 (如果不滿足這個條件,則允許讀取 返回除最近寫入之外的寫入結果。)因此,它是一個很好的做法(並且實際上有時在Linux下有必要)將 設置爲fseek(3)或fgetpos(3)在這樣的流上的寫入和讀取操作 之間的操作。此操作可能是一個明顯的無操作(如 FSEEK(...,0L,SEEK_CUR)要求其同步的副作用。

所以,你應該始終調用fseek()(如如。fseek(..., 0, SEEK_CUR))在從文件讀取和寫入之間切換時。

+1

這是問題所在,這就是我閱讀MSDN文檔而不是手冊頁所得到的結果。 :) 謝謝。 – Mike 2013-02-14 16:08:16

+0

請注意,來自MSDN(VS 2012)的最新文檔已更新:http://msdn.microsoft.com/en-us/library/yeby3zcb.aspx – 2013-02-14 16:16:35

+0

@MichaelBurr - 好點,這不是最最近的文檔,我應該更新我的書籤,過了一段時間,因爲我去過那裏。 – Mike 2013-02-14 16:22:54

3

在輸入之後執行輸出之前,fflush()不是什麼好事 - 您需要執行查找操作。類似:

fseek(fp, ftell(fp), SEEK_SET); // not fflush(fp); 

從C99標準(7.19.5.3/6「則fopen functoin):

當一個文件被打開與更新模式( '+' 作爲第二或第三 字符在上面的模式參數值列表中),輸入和 輸出都可以在關聯的數據流上執行,但輸出 不應直接跟隨輸入,而不需要中間調用fflush函數的 或文件定位功能(fseek, fsetpos或倒帶),並且輸入不應該直接跟在輸出 之後,除非 輸入操作遇到文件結束,否則不會調用文件定位功能。

+0

這很有趣,你說「fflush()不是什麼好事」,但是你引用的C99片段說:「沒有對fflush函數或文件定位函數的干預調用。所以,就在那裏,它表示「fflush()'或'fseek()'/其他定位函數。 – Mike 2013-02-14 16:24:28

+2

這是輸出後輸入。你的問題是在執行輸入後輸出,這需要一個介入文件定位調用(或EOF)。我會說,爲了讓所有的條件都能在你的腦海中暢通無阻,閱讀起來會很棘手 - 一張桌子會更好。 – 2013-02-14 16:38:28

+0

+1得到它,這使得訂購很重要的原因。感謝您的意見。 – Mike 2013-02-14 19:21:13