2010-07-13 49 views
6

我來自一個C和C++背景,但也有一些網絡的東西玩。所有的美國C鄉親(希望)知道,做一個讀之前調用一個FILE*feof是錯誤的。這是經常給C和C++帶來新手的東西。 PHP的實現也是這種情況嗎?PHP的FEOF行爲與C'S

我想,這一定是因爲該文件可能是一個插座或其他任何地方不可能知道讀完之前的大小。但是,幾乎所有的PHP例子(甚至那些php.net發現我見過的看起來像這樣(和報警在我的腦海熄滅):

$f = fopen("whatever.txt", "rb"); 
while(!feof($f)) { 
    echo fgets($f); 
} 
fclose($f); 

我知道這是最好寫這樣避免此問題:

$f = fopen("whatever.txt", "rb"); 
while($line = fgets($f)) { 
    echo $line; 
} 
fclose($f); 

但是這是除了點我試圖測試,如果,如果我做了「錯誤的方式」的事情會失敗,但我無法得到它導致不正確的行爲,這是不完全科學的,。但我想這是值得一試。

那麼,是不是不正確在PHP中fread之前調用feof

PHP有幾種方式可以做到與C版本不同,但我覺得它們有缺點。

  • 他們可以將它默認爲!EOF。這是次優的,因爲它可能對某些角落案例不正確。

  • 他們可以在fopen調用期間獲取文件大小,但這不適用於所有類型的文件資源,導致不一致的行爲,並且速度會變慢。

回答

3

在你試圖讀取文件之前,PHP並不知道它是否在文件末尾。試試這個簡單的例子:

<?php 
$fp = fopen("/dev/null","rb"); 
while (!feof($fp)) { 
    $data = fread($fp, 1); 
    echo "read " . strlen($data) . " bytes"; 
} 
fclose($fp); 
?> 

你會得到一行read 0 bytes。即使您在技術上處於文件末尾,feof()也會返回true。通常是因爲fread($fp, 1)返回數據,和任何處理你正在做的,處理任何數據就好這不會導致出現問題。如果您確實需要知道您是否在文件末尾,則必須先進行讀取。

-1

您斷言在fread之前沒有撥打feof不正確 - 因此問題無效。

+5

您是否創建了您的帳戶才能爲我們提供這項寶貴的貢獻? – 2010-07-13 17:33:25

+0

在C中,在可以設置EOF標誌的操作之前調用'feof'肯定是一個邏輯錯誤。 'fopen'不是那些操作之一。 – 2010-07-13 17:46:13

+0

Arrrggghhh!這當然不是一個錯誤,邏輯,語法或其他。這是完全有效的。如果你明白它的作用 - 它會像預期的那樣行事,就像上面解釋的MightyE一樣。這個問題構成了一個錯誤;不是這樣。 – Anonymous 2010-07-19 21:00:18

0

這可能是一個比答案更多的問題,但爲什麼不使用file_get_contents()?根據我的經驗,如果你正在閱讀一個文件或一個流,這個函數爲你做了骯髒的工作(假設你想將整個資源讀入一個字符串,或者知道/可以計算一個限制和偏移量)。它的姐妹函數file_put_contents()運行良好,反過來。

例如,這裏有一個例子:

$expected_content = "Hello Stack Overflow!" 
$real_content = file_get_contents("/path/to/file.txt"); 
if ($expected_content != $real_content){ 
    file_put_contents("/path/to/file.txt", $real_content); 
} 

或流:

$expected_content = "Hello Stack Overflow!" 
$real_content = file_get_contents("http://host.domain.com/file.txt"); 
if ($expected_content != $real_content){ 
    $options = array('ftp' => array('overwrite' => true)); 
    $stream = stream_context_create($options); 
    file_put_contents("ftp://user:[email protected]/file.txt", $real_content, 0, $stream); 
} 

然後,你不必擔心EOF或任何東西,它會爲你(FTP放有點冒險,但沒關係)。當然,這在所有情況下都不起作用...

有沒有什麼我從原始問題中失蹤,使這種方法不可行?

+1

你的方法很好,完全合理,我的問題比實際更具學術性。我只是想知道PHP中的'foef'與C中的行爲是否一樣。謝謝。 – 2010-07-13 17:48:30

+1

啊,學者,我沒有看到你的皮夾克花呢肘部8o) (荷馬辛普森FTW,「更正,我毀了兩件夾克!」) – Tim 2010-07-13 18:27:41