2014-10-27 150 views
0

的fopen示例失敗文件被刪除後文件打開問題。的fopen狀態在VC

#include <stdio.h> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    FILE * pFile; 
    for(int i=0; i < 1000000; i++) 
    { 
     bool ret = remove("C:\\abc.txt"); 
     pFile = fopen ("C:\\abc.txt","w"); 
     if (pFile!=NULL) 
     { 
      fputs ("fopen example",pFile); 
      fclose (pFile); 
     } 
     else 
     { 
      printf("%d fopen() fails \n", count); 
     } 
    } 
    return 0; 
} 

在此,刪除被調用,PFILE =的fopen( 「C:\的abc.txt」, 「W」)之後;被調用,

有時即使在C:\中,abc.txt文件在remove被調用後也不存在,但fopen pFile指針爲null。

這是一些不總是轉載。在這個例子中,這個問題被轉載50/60次。

請提出一些解決方案。

+3

您是否嘗試過檢查errno變量?它可能會被系統設置爲一些錯誤代碼,這可能會幫助你解決這個問題,你可以使用perror來收集更多的信息。也看看http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html – fjanisze 2014-10-27 09:15:39

+0

看起來像一個競爭條件。底層文件系統中可能的優化可以讓'remove'在真正清除所有內容之前返回,並立即創建具有相同名稱的文件。嘗試在刪除和創建之間添加短暫的睡眠:它應該起作用。 – 2014-10-27 09:21:54

+0

如果您想以「w」模式打開文件,請刪除文件,我認爲您不需要。 – BLUEPIXY 2014-10-27 09:51:12

回答

1

如果您已經確定是是競爭條件在底層文件系統中的問題,要解決它是(通過BLUEPIXY的建議),以簡單地去掉remove調用正確的方法:

pFile = fopen ("C:\\abc.txt","w"); 

將創建該文件,如果它不存在,並將其截斷爲0大小(如果它存在),那麼正是您所需要的。

+0

我正在使用包裝函數,其中給出fopen調用。如果文件被刪除,它將以寫模式打開,否則以rb +模式打開。因此,在應該刪除並重新創建的情況下,會出現問題。 另外我檢查了remove()函數的返回值,以確認刪除是否成功,令我驚訝的是,我發現有時刪除返回成功的值,並進一步fopen失敗給予「權限被拒絕」作爲錯誤,有時remove()函數失敗但fopen是成功的。刪除()似乎是不可靠的函數。 – Aakash 2014-10-27 11:16:20

+0

@Aakash:'remove'不是靠它的一個不可靠的函數。但是在Windows下,如果在打開的文件上調用(特殊訪問模式除外),它會失敗,所以你有相同的種族問題。恕我直言,你應該重新考慮你的算法,不要執行移除調用。 *在您的用例條件*中是不安全的。 – 2014-10-27 11:35:20

+0

謝謝您的信息。我會檢查其他方式。謝謝。 – Aakash 2014-10-28 03:13:06

0

如果您需要在文件被移除後確定創建文件,您可以延遲打開文件,直到您確認刪除了舊的「abc.txt」文件。

對於您需要引入一些循環,以確認它像下面,

bool ret = remove("C:\\abc.txt"); 
FILE * rFile; 
while(true) 
{ 
    rFile = fopen ("C:\\abc.txt","r"); 
    if(rfile == null) 
     break; //File Removed confirmed!! 
    else 
     sleep(100); //Loop around again... 
} 
pFile = fopen ("C:\\abc.txt","w"); 
if (pFile!=NULL)