Manipulação de arquivos
Esta aula aborda a manipulação de arquivos em PHP, incluindo funções tradicionais como fopen, fread e fwrite, além de alternativas modernas como file_get_contents. Exploramos também o conceito de streams e boas práticas de tratamento de erros, com exemplos práticos e exercícios.
Nesta aula, vamos explorar a manipulação de arquivos em PHP, uma habilidade essencial para qualquer desenvolvedor que precise ler, escrever ou gerenciar dados persistentes. Você aprenderá desde as funções clássicas como fopen, fread e fwrite, até abordagens mais modernas e convenientes como file_get_contents. Além disso, entenderemos o conceito de streams, que são a base de toda a E/S de arquivos em PHP, e como lidar com erros de forma robusta.
Ao final desta aula, você terá uma compreensão sólida de como trabalhar com arquivos, escolher a melhor função para cada situação e escrever código defensivo que lida bem com falhas. Vamos começar com as funções tradicionais e depois avançar para técnicas mais avançadas.
fopen, fread, fwrite
As funções fopen, fread e fwrite são as funções clássicas de manipulação de arquivos em PHP. Elas oferecem controle fino sobre o processo de leitura e escrita, permitindo que você trabalhe com arquivos de forma incremental, o que é útil para arquivos grandes ou quando você precisa de controle sobre o buffer.
fopen abre um arquivo ou URL e retorna um recurso (resource) que representa o fluxo. O segundo parâmetro é o modo de abertura, que determina se você vai ler, escrever, anexar, etc. Os modos mais comuns são:
r– abre para leitura, posiciona o ponteiro no início.w– abre para escrita, truncando o arquivo (ou criando se não existir).a– abre para escrita, posicionando o ponteiro no final (append).r+– abre para leitura e escrita, posiciona no início.w+– abre para leitura e escrita, truncando o arquivo.a+– abre para leitura e escrita, posiciona no final.
Depois de aberto, você usa fread para ler um número específico de bytes, ou fgets para ler uma linha. Para escrever, use fwrite, que aceita a string a ser escrita e, opcionalmente, o número de bytes. Sempre feche o arquivo com fclose para liberar recursos.
Exemplo de escrita e leitura:
<?php
// Escrevendo em um arquivo
$arquivo = 'exemplo.txt';
$handle = fopen($arquivo, 'w');
if ($handle) {
fwrite($handle, "Linha 1\n");
fwrite($handle, "Linha 2\n");
fclose($handle);
} else {
echo "Erro ao abrir o arquivo.";
}
// Lendo o arquivo
$handle = fopen($arquivo, 'r');
if ($handle) {
while (($linha = fgets($handle)) !== false) {
echo $linha;
}
fclose($handle);
}
?>
Note que fgets lê até encontrar uma nova linha ou o tamanho especificado. Se você quiser ler todo o conteúdo de uma vez, pode usar file_get_contents, que veremos a seguir.
file_get_contents
A função file_get_contents é uma alternativa mais simples e direta para ler o conteúdo de um arquivo inteiro em uma string. Ela é recomendada quando você precisa do conteúdo completo do arquivo e não precisa de controle fino sobre a leitura. Exemplo:
<?php
$conteudo = file_get_contents('exemplo.txt');
echo $conteudo;
?>
Além de ler arquivos locais, file_get_contents também pode ler URLs, desde que a configuração allow_url_fopen esteja habilitada. Isso é útil para fazer requisições HTTP simples. Por exemplo:
<?php
$json = file_get_contents('https://api.exemplo.com/dados');
$dados = json_decode($json, true);
?>
Para escrever em um arquivo de forma simples, existe a função file_put_contents, que é o equivalente para escrita. Ela aceita o caminho do arquivo, os dados a serem escritos e flags opcionais como FILE_APPEND para anexar. Exemplo:
<?php
file_put_contents('exemplo.txt', "Novo conteúdo\n", FILE_APPEND);
?>
Essas funções são mais concisas e geralmente suficientes para a maioria dos casos, mas é importante conhecer as funções tradicionais para quando você precisar de mais controle.
Streams
Em PHP, todos os recursos de arquivos são baseados no conceito de streams. Um stream é uma abstração que representa um fluxo de dados que pode ser lido ou escrito, como um arquivo, uma conexão de rede, ou até mesmo uma string em memória. Cada stream tem um tipo e um protocolo, por exemplo, file:// para arquivos locais, http:// para URLs, php:// para streams especiais.
Os streams permitem que você use funções como fopen e fread de forma uniforme para diferentes fontes de dados. Por exemplo, você pode abrir uma URL com fopen e ler como se fosse um arquivo local:
<?php
$handle = fopen('https://www.php.net', 'r');
if ($handle) {
$conteudo = stream_get_contents($handle);
fclose($handle);
echo $conteudo;
}
?>
O PHP também fornece streams especiais como php://input (para ler o corpo de requisições POST), php://output (para escrever na saída), e php://memory / php://temp (para armazenar dados em memória). Exemplo de uso de php://memory:
<?php
$handle = fopen('php://memory', 'r+');
fwrite($handle, "Dados temporários");
rewind($handle); // volta para o início
echo stream_get_contents($handle); // Lê todo o conteúdo
fclose($handle);
?>
Há também funções específicas para trabalhar com streams, como stream_get_contents (lê o restante do stream), stream_copy_to_stream (copia de um stream para outro), e stream_filter_append (aplica filtros como compressão). Dominar streams é fundamental para entender como o PHP gerencia dados.
Tratamento de erros
Ao manipular arquivos, muitos erros podem ocorrer: arquivo não existe, permissão negada, disco cheio, etc. Ignorar esses erros pode levar a falhas silenciosas ou mensagens confusas. Portanto, é crucial implementar tratamento de erros adequado.
Uma abordagem comum é verificar se a função de abertura retornou false e então lançar uma exceção ou exibir uma mensagem. Exemplo com fopen:
<?php
$arquivo = 'dados.txt';
$handle = @fopen($arquivo, 'r');
if ($handle === false) {
// Use error_get_last() para obter detalhes
$erro = error_get_last();
throw new RuntimeException("Falha ao abrir arquivo: " . $erro['message']);
}
?>
O operador @ suprime avisos do PHP, mas é melhor usar o manejo de erros com exceções. A partir do PHP 8, fopen lança uma exceção ValueError se o modo for inválido, mas para erros de sistema, ainda retorna false.
Outra técnica é usar file_get_contents com o parâmetro use_include_path e verificar o retorno:
<?php
$conteudo = @file_get_contents('inexistente.txt');
if ($conteudo === false) {
// Pode lançar exceção ou registrar erro
error_log("Não foi possível ler o arquivo.");
}
?>
Também é possível configurar um manipulador de erros personalizado com set_error_handler para converter avisos em exceções, mas isso é mais avançado. Para a maioria dos casos, verificar o retorno é suficiente.
Uma boa prática é usar try/catch com exceções personalizadas. Por exemplo:
<?php
function lerArquivo(string $caminho): string {
if (!file_exists($caminho)) {
throw new InvalidArgumentException("Arquivo não encontrado: $caminho");
}
$conteudo = file_get_contents($caminho);
if ($conteudo === false) {
throw new RuntimeException("Falha ao ler arquivo.");
}
return $conteudo;
}
try {
$dados = lerArquivo('config.php');
} catch (Exception $e) {
echo "Erro: " . $e->getMessage();
}
?>
Isso torna o código mais limpo e fácil de depurar. Lembre-se de sempre fechar arquivos abertos, mesmo em caso de erro, usando finally ou garantindo que fclose seja chamado.
Referências
- Documentação oficial: fopen
- Documentação oficial: fread
- Documentação oficial: fwrite
- Documentação oficial: file_get_contents
- Documentação oficial: Streams
- Documentação oficial: set_error_handler
Exercícios
-
Crie um script PHP que abra um arquivo chamado "log.txt" no modo de escrita, escreva três linhas de texto e feche o arquivo. Em seguida, abra o arquivo no modo leitura e exiba seu conteúdo.
✓ Resposta:<?php // Escreve $handle = fopen('log.txt', 'w'); fwrite($handle, "Primeira linha\n"); fwrite($handle, "Segunda linha\n"); fwrite($handle, "Terceira linha\n"); fclose($handle); // Lê $handle = fopen('log.txt', 'r'); echo stream_get_contents($handle); fclose($handle); ?> -
Usando
file_get_contentsefile_put_contents, leia o conteúdo de um arquivo "entrada.txt", converta todo o texto para letras maiúsculas e salve em "saida.txt".✓ Resposta:<?php $conteudo = file_get_contents('entrada.txt'); if ($conteudo !== false) { $conteudo = strtoupper($conteudo); file_put_contents('saida.txt', $conteudo); } else { echo "Erro ao ler entrada.txt"; } ?> -
Explique o que é um stream em PHP e dê dois exemplos de streams especiais. Qual a vantagem de usar streams?
✓ Resposta: Um stream é uma abstração de fluxo de dados que pode ser lido ou escrito. Exemplos de streams especiais:php://memory(armazenamento em memória) ephp://input(dados da requisição). A vantagem é que você pode usar as mesmas funções de arquivo para diferentes fontes de dados, tornando o código mais portável e flexível. -
Escreva uma função que leia um arquivo e retorne seu conteúdo como string. Se o arquivo não existir ou não puder ser lido, lance uma exceção com uma mensagem clara.
✓ Resposta:<?php function lerArquivo(string $caminho): string { if (!file_exists($caminho)) { throw new InvalidArgumentException("Arquivo não encontrado: $caminho"); } $conteudo = file_get_contents($caminho); if ($conteudo === false) { throw new RuntimeException("Falha ao ler arquivo: $caminho"); } return $conteudo; } ?> -
Cite três boas práticas ao manipular arquivos em PHP e explique cada uma.
✓ Resposta:- Verificar erros: Sempre verifique o retorno das funções de arquivo (ex.:
false) e trate adequadamente. - Fechar arquivos: Use
fcloseoufinallypara liberar recursos, mesmo em caso de exceção. - Usar exceções: Lance exceções para erros críticos, tornando o código mais fácil de depurar e manter.
- Verificar erros: Sempre verifique o retorno das funções de arquivo (ex.:
Boas Práticas e Observações Finais
Ao manipular arquivos, é importante considerar a segurança, especialmente se os nomes de arquivos vêm de entradas do usuário. Evite caminhos absolutos e valide entradas. Além disso, para arquivos grandes, prefira ler em partes com fread em vez de carregar tudo na memória com file_get_contents.
Outra dica: use file_put_contents com a flag LOCK_EX para evitar problemas de concorrência em escritas simultâneas. E lembre-se de que, em ambientes de produção, o diretório de escrita deve ter permissões adequadas.
Dominar a manipulação de arquivos é um passo fundamental para se tornar um desenvolvedor PHP completo. Pratique os exercícios e explore a documentação oficial para aprofundar seus conhecimentos.