Pergunta

Eu venho de uma experiência em C e C++, mas também brinco com algumas coisas da web.Todos nós, pessoal C (espero), sabemos que ligar feof com um FILE* antes de fazer uma leitura é um erro.Isso é algo que incomoda os novatos em C e C++ com muita frequência.Este também é o caso da implementação do PHP?

Acho que deve ser porque o arquivo pode ser um soquete ou qualquer outra coisa onde seja impossível saber o tamanho antes de terminar a leitura.Mas quase todos os exemplos de PHP (mesmo aqueles encontrados em php.net Eu vi algo parecido com isto (e os alarmes disparam na minha cabeça):

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

Eu sei que é preferível escrever assim e evitar esse problema:

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

mas isso não vem ao caso.Tentei testar se as coisas falhariam se eu fizesse "da maneira errada", mas não consegui causar comportamento incorreto.Isso não é exatamente científico, mas achei que valia a pena tentar.

Então, é incorreto ligar feof antes de um fread em PHP?

Existem algumas maneiras pelas quais o PHP poderia ter feito isso de forma diferente da versão C, mas sinto que elas têm desvantagens.

  • eles poderiam ter o padrão !EOF.Isso não é ideal porque pode estar incorreto em alguns casos extremos.

  • eles poderiam obter o tamanho do arquivo durante um fopen chamada, mas isso não funcionaria em todos os tipos de recursos de arquivo, gerando um comportamento inconsistente e seria mais lento.

Foi útil?

Solução

O PHP não sabe se está no final do arquivo até que você tente lê-lo.Experimente este exemplo simples:

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

Você receberá uma leitura de linha read 0 bytes.feof() retornou verdadeiro mesmo que você estivesse tecnicamente no final do arquivo.Geralmente isso não causa problema porque fread($fp, 1) não retorna dados, e qualquer processamento que você esteja fazendo não lida perfeitamente com dados.Se você realmente precisa saber se está no final do arquivo, primeiro você precisa fazer uma leitura.

Outras dicas

Isto pode ser mais uma pergunta do que uma resposta, mas por que não usar arquivo_get_contents()?Na minha experiência, se você estiver lendo um arquivo ou fluxo, esta função fará o trabalho sujo para você (supondo que você queira ler o recurso inteiro em uma string ou saber/poder calcular um limite e deslocamento).Sua função irmã file_put_contents() funciona bem, ao contrário.

Por exemplo, aqui está um exemplo:

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

ou um fluxo:

$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:pass@host.domain.com/file.txt", $real_content, 0, $stream);
}

Então você não precisa se preocupar com EOF nem nada, ele faz isso por você (ftp put fica um pouco arriscado, mas tudo bem).Claro, isso não funcionará em todas as situações...

Há algo que está faltando na pergunta original que torna essa abordagem inviável?

Sua afirmação sobre não ligar feof antes de um fread não está correto - conseqüentemente a pergunta não é válida.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top