2010-07-13 20 views
6

Provengo da uno sfondo C e C++ ma gioco anche con alcune cose del web. Tutti noi C (speriamo) sappiate che chiamare feof su un FILE* prima di fare una lettura è un errore. Questo è qualcosa che punge i neofiti a C e C++ molto spesso. Questo è anche il caso dell'implementazione di PHP?Comportamento di feof di PHP rispetto a C

Immagino che deve essere perché il file potrebbe essere una presa o qualsiasi altra cosa in cui è impossibile conoscere la dimensione prima di terminare la lettura. Ma quasi ogni esempio PHP (anche quelli che si trovano sul php.net ho visto simile a questa (e gli allarmi si spengono nella mia testa):

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

So che è preferibile scrivere questo come questo ed evitare questo problema:

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

ma questo è oltre il punto ho provato il test se le cose sarebbero fallire se l'ho fatto "nel modo sbagliato", ma non ho potuto farlo per causare un comportamento scorretto Questo non è esattamente scientifica,.. ma ho pensato che valesse la pena provare.

Quindi, non è corretto chiamare feof prima di un fread in PHP?

Ci sono un paio di modi in cui PHP avrebbe potuto fare diversamente questa versione di C, ma sento che hanno dei svantaggi.

  • avrebbero potuto impostarlo come predefinito! EOF. Questo è non ottimale perché potrebbe non essere corretto per alcuni casi d'angolo.

  • potrebbero ottenere la dimensione del file durante una chiamata fopen, ma questo non potrebbe funzionare su tutti i tipi di risorse di file, comportando un comportamento incoerente e sarebbe più lento.

risposta

3

PHP non sa se si trova alla fine del file finché non si è tentato di leggerlo. Provate questo semplice esempio:

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

Otterrete una linea di lettura read 0 bytes. feof() ha restituito true anche se tecnicamente alla fine del file. Solitamente questo non causa problemi poiché fread($fp, 1) non restituisce alcun dato e qualsiasi elaborazione si sta svolgendo non gestisce i dati. Se hai davvero bisogno di sapere se sei alla fine del file, devi prima fare una lettura.

-1

La tua affermazione sul non chiamare feof prima che un fread non sia corretta - di conseguenza la domanda non è valida.

+5

Hai creato il tuo account solo per darci questo prezioso contributo? –

+0

in C è sicuramente un errore logico chiamare 'feof' prima di un'operazione che può impostare il flag EOF. 'fopen' non è una di quelle operazioni. –

+0

Arrrggghhh! Non è certamente un errore, logico, sintattico o altro. È perfettamente valido Se capisci cosa fa, si comporterà esattamente come previsto, come spiegato in precedenza da MightyE. La domanda incorniciava la condizione come un errore; non è. – Anonymous

0

Questa potrebbe essere più una domanda che una risposta, ma perché non utilizzare file_get_contents()? Nella mia esperienza, se stai leggendo un file o uno stream, questa funzione fa il lavoro sporco per te (assumendo che tu voglia leggere l'intera risorsa su una stringa, o sapere/può calcolare un limite e un offset). La sua funzione sorella file_put_contents() funziona bene, al contrario.

Per esempio, ecco un esempio:

$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); 
} 

o un flusso di:

$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); 
} 

Quindi non c'è bisogno di preoccuparsi di EOF o qualcosa, lo fa per voi (put ftp diventa un po 'rischioso, ma va bene). Naturalmente, questo non funzionerà in tutte le situazioni ...

C'è qualcosa che mi manca dalla domanda originale che rende questo approccio non fattibile?

+1

Il tuo approccio è corretto e del tutto ragionevole, la mia domanda è più accademica che pratica. Volevo solo sapere se 'foef' in PHP ha lo stesso comportamento di C. Grazie. –

+1

Ah, un accademico, non ho visto la tua giacca di pelle con i gomiti di tweed 8o) (Homer Simpson FTW, "CORREZIONE, ho rovinato due giacche!") – Tim

Problemi correlati