Manipulando Arquivos em PHP

Manipular arquivos é uma habilidade essencial no desenvolvimento web, especialmente em aplicações que envolvem upload de arquivos, geração de relatórios, registro de logs, processamento de dados ou integração com sistemas legados. O PHP, desde suas primeiras versões, oferece uma API robusta e flexível para trabalhar com arquivos no servidor. Neste artigo, você vai aprender como abrir, ler, escrever, excluir e gerenciar arquivos utilizando PHP.

Abrindo um arquivo

O PHP possui diversas funções para manipulação de arquivos, e algumas delas exigem que seja passado um resource, que representa uma conexão ativa com um arquivo.

fopen(filename, mode)

Podemos criar um resource que aponta para um arquivo utilizando a função fopen(), que recebe como parâmetros o path do arquivo (filename) e uma string que define o modo de abertura desse arquivo.

Modos de Arquivo

“r”Abre o arquivo para leitura, posicionando o ponteiro no início do arquivo. Caso o arquivo não exista, a função retorna false.
“r+”
Abre o arquivo para leitura e escrita, posicionando o ponteiro no início do arquivo. Caso o arquivo não exista, a função retorna false.
“w”Abre o arquivo para escrita. Se o arquivo não existir, ele será criado. Se já existir, seu conteúdo será truncado (apagado). O ponteiro é posicionado no início do arquivo.
“w+”Abre o arquivo para leitura e escrita. Se o arquivo não existir, ele será criado. Caso já exista, seu conteúdo será truncado (apagado). O ponteiro é posicionado no início do arquivo.
“a”Abre o arquivo para escrita, posicionando o ponteiro no final do arquivo. Se o arquivo não existir, ele será criado. ATENÇÃO: a função fseek() não tem efeito em arquivos abertos no modo “a”; todas as escritas sempre ocorrerão no final do arquivo.
“a+”Abre o arquivo para leitura e escrita, posicionando o ponteiro no final do arquivo. Se o arquivo não existir, ele será criado. ATENÇÃO: a função fseek() afeta apenas o ponteiro de leitura; as operações de escrita sempre ocorrem no final do arquivo, independentemente da posição do ponteiro.
“x”Abre o arquivo para escrita somente se ele não existir. Se o arquivo já existir, a função retorna false e gera um erro do tipo E_WARNING.
“x+”Semelhante ao modo “x”, porém abre o arquivo para leitura e escrita. Se o arquivo já existir, retorna false e gera um erro do tipo E_WARNING.
“c”Abre o arquivo para escrita, mas diferente do modo “w”, não trunca (não apaga) o conteúdo existente. Se o arquivo não existir, ele será criado. O ponteiro é posicionado no início do arquivo.
“c+”Semelhante ao modo “c”, porém abre o arquivo para leitura e escrita. Não trunca o conteúdo existente e, se o arquivo não existir, ele será criado. O ponteiro é posicionado no início do arquivo.
Resumo dos modos disponíveis para abertura de arquivos da função fopen.

Vamos a um exemplo

$arquivo = fopen('arquivo.txt', 'r');

if ($arquivo) {
    echo "Arquivo aberto com sucesso!";
    fclose($arquivo);
} else {
    echo "Falha ao abrir o arquivo.";
}

fread, fwrite, fgetc, fgets, fseek, etc.

Uma vez que o arquivo está aberto, podemos manipulá-lo utilizando várias funções que recebem o ponteiro do arquivo como parâmetro. A seguir, vamos conhecer algumas delas.

fread(file_resource, length)

A função fread() lê uma quantidade de bytes, definida pelo parâmetro length, a partir de um recurso de arquivo e retorna esses dados. Caso não haja mais bytes para ler, ela retorna false.

$arquivo = fopen('arquivo.txt', 'r');

echo fread($arquivo, 7);

fclose($arquivo);

No exemplo acima, abrimos o arquivo para leitura com o modo “r”, que posiciona o ponteiro no início do arquivo. A partir desse ponto, lemos os 7 primeiros bytes. É importante lembrar que, após essa leitura, o ponteiro do arquivo avança 7 bytes, ficando posicionado na próxima posição para uma leitura subsequente.

É importante lembrar que nem todos os caracteres em PHP são representados por apenas 1 byte. Acentos e outros caracteres especiais, especialmente em codificações como UTF-8, podem ocupar mais de um byte. Como a função fread() realiza a leitura em bytes, isso pode causar comportamentos inesperados ao lidar com textos que contenham esses caracteres.

// arquivo.txt
Hoje é um bom dia!

//exemplo.php
$arquivo = fopen('arquivo.txt', 'r');
echo fread($arquivo, 6);
fclose($arquivo);

// Saída
Hoje �

Note que, no conteúdo de arquivo.txt, o sexto caractere é “é”, que ocupa 2 bytes em UTF-8. Ao ler 6 bytes a partir do início do arquivo, capturamos apenas o primeiro byte desse caractere, o que resulta em um caractere corrompido na saída, pois a leitura foi incompleta.

fgetc(file_resource)

A função fgetc() lê um único caractere do recurso de arquivo e o retorna como uma string. Caso não haja mais caracteres para serem lidos, ela retorna false.

// arquivo.txt
PHP!

//exemplo.php
$arquivo = fopen('arquivo.txt', 'r');

echo fgetc($arquivo); // P
echo fgetc($arquivo); // H
echo fgetc($arquivo); // P
echo fgetc($arquivo); // !

fclose($arquivo);

fgets(file_resource, length = null)

A função fgets() lê uma linha do arquivo até encontrar um caractere de fim de linha (PHP_EOL) e retorna o conteúdo como uma string. Caso o parâmetro length seja informado, a leitura será interrompida ao atingir o número de bytes especificado ou ao encontrar o fim da linha — o que ocorrer primeiro.

// arquivo.txt 
PHP!
-----
É uma linguaguem muito interessante.

// exemplo.php
$arquivo = fopen('arquivo.txt', 'r');

echo '> ' . fgets($arquivo); 
echo '> ' . fgets($arquivo); 
echo '> ' . fgets($arquivo); 

fclose($arquivo);

// saída
> PHP!
> -----
> É uma linguaguem muito interessante.

Lendo até o fim

Como as funções fgetc, fgets e fread retornam false ao atingir o final do arquivo, podemos utilizá-las dentro de um laço para realizar a leitura até o fim de forma bastante simples.

$arquivo = fopen('arquivo.txt', 'r');

while( $c = fgetc($arquivo)){
    echo $c;
}
fclose($arquivo);

Também podemos utilizar a função feof(file_resource) para verificar se o ponteiro do arquivo chegou ao final.

$arquivo = fopen('arquivo.txt', 'r');

while( !feof($arquivo) ){
    echo fgetc($arquivo);
}
fclose($arquivo);

fwrite(file_resource, data, length = null)

Para escrever em um arquivo, utilizamos a função fwrite(), que recebe como parâmetros o recurso de arquivo, uma string (data) contendo o conteúdo a ser gravado e, opcionalmente, um length em bytes. Esse último define o número máximo de bytes que serão escritos. Caso o length seja informado, serão gravados no arquivo até length bytes ou até o final da string data, o que acontecer primeiro.

$arquivo = fopen('arquivo.txt', 'w');

fwrite($arquivo, "Linguagem ");
fwrite($arquivo, "PHP");

fclose($arquivo);

No exemplo acima, abrimos o arquivo para escrita utilizando o modo “w”, que apaga o conteúdo existente caso o arquivo já exista. Em seguida, gravamos as strings “Linguagem “ e “PHP”. Perceba que, a cada escrita, o ponteiro do arquivo é automaticamente avançado de acordo com o tamanho dos dados gravados, fazendo com que o conteúdo seja escrito de forma sequencial, um após o outro.

Adicionando ao final do arquivo

Lembrando que, se quisermos adicionar conteúdo ao final de um arquivo, sem sobrescrever o que já existe, devemos abri-lo utilizando o modo “a”.

$arquivo = fopen('arquivo.txt', 'a');

fwrite($arquivo, " - no final");

fclose($arquivo);

fclose(resource)

A função fclose() é responsável por fechar o arquivo, liberando os recursos associados a ele.

$arquivo = fopen('arquivo.txt', 'w+');

// operações com o arquivo

fclose($arquivo);

fseek(resource, offset, whence = SEEK_SET)

Como vimos nas funções anteriores, a leitura e gravação no arquivo ocorrem na posição indicada pelo ponteiro do arquivo. Esse ponteiro é automaticamente movimentado pelas operações de leitura, escrita ou conforme o modo de abertura do arquivo. A função fseek() permite alterar manualmente a posição do ponteiro, recebendo como parâmetros o recurso do arquivo, um offset (deslocamento em bytes) e o parâmetro whence, que define o ponto de referência para o deslocamento. O whence pode assumir os seguintes valores:

  • SEEK_SET – Define a posição do ponteiro como o início do arquivo mais o valor de offset em bytes.
  • SEEK_CUR – Define a posição como a posição atual do ponteiro mais offset bytes.
  • SEEK_END – Define a posição como o final do arquivo mais offset bytes (valores negativos posicionam antes do final).
$arquivo = fopen('arquivo.txt', 'w+');

fwrite($arquivo, "Programador PHP");
fseek($arquivo, 12); 
echo fread($arquivo, 3); 

fclose($arquivo);

// Saída 
// PHP

No exemplo acima, escrevemos no arquivo a string “Programador PHP” e, em seguida, movemos o ponteiro para a posição 12, ou seja, 12 bytes a partir do início do arquivo, posicionando-o logo após o espaço. A partir dessa posição, lemos os próximos 3 bytes, que correspondem à palavra “PHP”.

fwrite($arquivo, "Programador PHP");
fseek($arquivo, -3, SEEK_END);
echo fread($arquivo, 3);

fclose($arquivo);

// Saída 
// PHP

Neste outro exemplo, escrevemos novamente o mesmo texto, mas desta vez utilizamos SEEK_END na função fseek() para definir o final do arquivo como ponto de referência. Passamos -3 como offset para mover o ponteiro 3 bytes para trás a partir do final. Com isso, conseguimos ler os últimos 3 bytes do arquivo.

ftell(file_resource)

A função ftell() retorna a posição atual do ponteiro de leitura/escrita dentro do arquivo, em bytes, a partir do início.

$arquivo = fopen('arquivo.txt', 'w+');

fwrite($arquivo, "ABC");
echo ftell($arquivo); // 3

tmpfile()

A função tmpfile() cria um recurso de arquivo temporário com um nome único, que é automaticamente deletado quando é fechado, seja explicitamente com a função fclose() ou quando o script é encerrado.

$arquivo = tmpfile();

fwrite($arquivo, "PHP");
fseek($arquivo, 0);
echo fread($arquivo, 20);

fclose($arquivo);

Funções de mais alto nível

As funções apresentadas anteriormente, embora eficientes e versáteis, podem ser um pouco mais complexas de usar por exigirem a manipulação direta do ponteiro do arquivo. Em muitas situações, é mais simples utilizar funções de mais alto nível, como file_get_contents e file_put_contents, que abstraem essa complexidade.

file_get_contents(filename) – Lendo um arquivo inteiro

A função file_get_contents() lê todo o conteúdo de um arquivo e o retorna como uma única string. Ela também aceita vários parâmetros opcionais para personalizar a leitura, como offset, length e context.

  • filename: Caminho ou URL do arquivo a ser lido.
  • use_include_path: Define se o PHP deve procurar o arquivo também no include_path especificado no php.ini. O padrão é false.
  • context: Um recurso de contexto de stream, utilizado para configurar opções como cabeçalhos HTTP, autenticação, tempo limite, método de requisição (GET, POST), entre outros. Não é necessário para leitura de arquivos locais.
  • offset: Define a posição, em bytes, a partir da qual a leitura deve começar.
  • length: Especifica quantos bytes devem ser lidos a partir do offset.
// arquivo.txt
A Linguagem PHP é Fantástica!

// exemplo.php
$content = file_get_contents('arquivo.txt');
echo $content;
// Saída:
// A Linguagem PHP é Fantástica!

echo file_get_contents('arquivo.txt', false, null, 12, 3);
// Saída:
// PHP

No exemplo, a linha 5 lê todo o conteúdo do arquivo e o retorna como uma string; já a linha 10 inicia a leitura a partir do byte 12 e obtém apenas 3 bytes, resultando na sequência “PHP”.

file_put_contents(filename, data) – Escrevendo um arquivo inteiro

A função file_put_contents() escreve o conteúdo informado em data dentro do arquivo especificado em filename.

file_put_contents('arquivo.txt', "O conteudo \n do arquivo!");

Por padrão, o conteúdo passado substituirá o conteúdo do arquivo, caso ele já exista. Para adicionar o novo conteúdo ao final do arquivo, podemos passar a flag FILE_APPEND como terceiro parâmetro.

file_put_contents('arquivo.txt', " - no final!", FILE_APPEND);

file(filename)

Lê todo o conteúdo de um arquivo e o retorna como um array, onde cada linha do arquivo corresponde a um elemento do array.

// arquivo.txt
Rodrigo
Tiago
Lucia
Mariana

// exemplo.php
$data = file('arquivo.txt');

print_r($data);
// Saída
// Array
// (
//     [0] => Rodrigo
//     [1] => Tiago
//     [2] => Lucia
//     [3] => Mariana
// )

Obtendo informações sobre um arquivo

Existem diversas funções em PHP que permitem obter informações sobre um arquivo, como seu tamanho, tipo, permissões, data de modificação, entre outras.

filesize(filename)

A função filesize() retorna o tamanho, em bytes, do arquivo especificado no parâmetro filename.

echo filesize('arquivo.txt'); // 31

mime_content_type(filename)

A função mime_content_type() retorna o tipo MIME do arquivo especificado, informando o tipo de conteúdo que ele representa, como text/plain, image/png, application/pdf, entre outros.

echo mime_content_type('arquivo.txt') . PHP_EOL; // text/plain
echo mime_content_type('foto.png') . PHP_EOL; // image/png
echo mime_content_type('arquivo.pdf') . PHP_EOL; // application/pdf

finfo_file

Também podemos obter o tipo MIME de um arquivo utilizando a função finfo_file(), que recebe como parâmetros um objeto finfo e o caminho do arquivo.

$finfo = finfo_open(FILEINFO_MIME_TYPE);

$mime = finfo_file($finfo,'arquivo.pdf');

echo $mime; // application/pdf

filectime e filemtime.

As funções filectime() e filemtime() retornam a data de modificação de um arquivo como um inteiro no formato timestamp. A principal diferença entre elas é que filemtime() retorna a data da última modificação do conteúdo do arquivo, enquanto filectime() retorna a data da última modificação do inode, o que inclui alterações nas permissões, proprietário e outras metainformações do sistema de arquivos.

$timestap_ctime = filectime('arquivo.txt');
echo date('d/m/Y H:i:s', $timestap_ctime ) . PHP_EOL;

$timestap_mtime = filemtime('arquivo.txt');
echo date('d/m/Y H:i:s', $timestap_mtime ). PHP_EOL;

// altere o arquivo e execute novamente o script
// após, altere as permissões do arquivo (chmod 777 arquivo.txt)
// e note que somente o ctime foi alterado

fileowner e posix_getpwuid

A função fileowner() retorna o ID do proprietário do arquivo como um valor inteiro. Para obter o nome do usuário e outras informações associadas a esse ID, podemos utilizar a função posix_getpwuid(), que recebe o ID e retorna um array com os dados do proprietário.

$owner_id = fileowner('arquivo.txt');

echo posix_getpwuid($owner_id)['name'] . PHP_EOL;

print_r(posix_getpwuid($owner_id));

// Saída
// rodrigo
// Array
// (
//     [name] => rodrigo
//     [passwd] => x
//     [uid] => 1000
//     [gid] => 1000
//     [gecos] => ,,,
//     [dir] => /home/rodrigo
//     [shell] => /usr/bin/zsh
// )

fileperms

A função fileperms() retorna as permissões de um arquivo como um número inteiro. Como esse valor pode ser difícil de interpretar diretamente, é comum utilizarmos a função sprintf() para convertê-lo para uma string no formato octal, que é mais familiar quando lidamos com permissões em sistemas Unix.

$perms = fileperms('arquivo2.txt') ;
echo $perms . PHP_EOL;
echo sprintf("%o", $perms) . PHP_EOL;

// Saída
// 33188
// 100644 

//(644 corresponde a rw-r--r--)

is_ …

O PHP oferece uma série de funções que começam com is_ para realizar verificações em um filename, como checar se o caminho é um arquivo, diretório, se ele é legível, executável, entre outras.

is_dir(filename)

Retorna true se o filename for um diretório. Caso contrário, retorna false.

$filename = "minha-pasta";

if(is_dir($filename)){
    echo "$filename é um diretório\n";
}

is_file(filename)

Retorna true se o filename for um arquivo. Caso contrário, retorna false.

$filename = "arquivo.txt";

if(is_file($filename)){
    echo "$filename é um arquivo\n";
}

is_readable(filename)

Retorna true se o arquivo ou diretório especificado tiver permissão de leitura. Caso contrário, retorna false.

$filename = "arquivo.txt";

if(is_readable($filename)){
    echo "$filename tem permissão de leitura\n";
}

is_writable(filename)

Retorna true se o arquivo ou diretório especificado tiver permissão de escrita. Caso contrário, retorna false.

$filename = "arquivo.txt";

if( is_writable($filename)){
    echo "$filename tem permissão de escrita\n";
}

is_executable(filename)

Retorna true se o arquivo tem permissão de escrita. Caso contrário false.

$filename = "arquivo.txt";

if( is_executable($filename)){
    echo "$filename tem permissão de execução\n";
}

file_exists(filename)

Retorna true se o arquivo especificado em filename existir. Caso contrário, retorna false.

$filename = "arquivo.txt";

if( file_exists($filename)){
    echo "$filename existe\n";
}else{
    echo "$filename não existe\n";
}

Deletando um arquivo

Para deletar um arquivo, utilizamos a função unlink(filename). Ela retorna true em caso de sucesso e false se ocorrer um erro. Caso o arquivo especificado não exista, será gerado um erro.

$filename = "old-file.txt";

if(file_exists($filename)){
    unlink($filename);
}

Renomeando um arquivo

Para renomear um arquivo, utilizamos a função rename(from, to), que recebe o nome atual do arquivo como from e o novo nome como to.

rename('arquivo.txt', 'novo-nome.txt');

Copiando um arquivo

Para criar uma cópia de um arquivo, utilizamos a função copy(from, to), que recebe como parâmetro o nome do arquivo de origem (from) e o nome do arquivo de destino (to), para onde o conteúdo será copiado.

copy('arquivo.txt', 'arquivo-copia.txt');

Alterando as permissões de um arquivo

Para alterar as permissões de um arquivo, utilizamos a função chmod(filename, permissions), que recebe o nome do arquivo e um valor inteiro representando as permissões. Como é comum usarmos o formato octal em sistemas Unix, podemos prefixar o número com 0 para indicar que se trata de uma permissão em base octal (por exemplo, 0755).

chmod('arquivo.txt', 0644);
// Resultado
// -rw-r--r--  1 rodrigo rodrigo      27 Jun 22 09:37  arquivo.txt

Alterando o proprietário e grupo de um arquivo

Podemos alterar o proprietário de um arquivo utilizando a função chown(filename, user), passando o nome do arquivo e o novo usuário. Para alterar o grupo, usamos a função chgrp(filename, group), informando o nome do arquivo e o grupo desejado.

$filename = "arquivo.txt";

chown('arquivo.txt', 'root');
chgrp('arquivo.txt', 'root');

// -rw-r--r--  1 root    root         27 Jun 22 09:37  arquivo.txt

Trabalhando com o caminho de um arquivo

O PHP oferece diversas funções para manipular e obter informações relacionadas ao caminho de um arquivo, facilitando o trabalho com diretórios, extensões, nomes de arquivos e seus componentes.

basename(path, suffix=””)

Retorna o nome do arquivo a partir de um caminho (path) informado. Se um suffix for passado, ele será removido do final do nome do arquivo, caso corresponda.

echo basename("/home/rodrigo/arquivo.txt") . PHP_EOL; // arquivo.txt
echo basename("./arquivo.txt") . PHP_EOL;              // arquivo.txt
echo basename("../arquivo.txt") . PHP_EOL;             // arquivo.txt
echo basename("docs/arquivo.txt", ".txt") . PHP_EOL;   // arquivo

dirname(path, level=1)

A função dirname() retorna o diretório pai do caminho especificado em path. O parâmetro opcional level define quantos níveis acima na hierarquia de diretórios devem ser retornados.

echo dirname("/home/rodrigo/arquivo.txt") . PHP_EOL; 
// /home/rodrigo

echo dirname("/home/rodrigo/arquivo.txt", 2) . PHP_EOL; 
// /home

echo dirname("/home/rodrigo/arquivo.txt", 3) . PHP_EOL; 
// /

realpath(path)

A função realpath() retorna o caminho absoluto e resolvido do arquivo especificado em path. Para que a função funcione corretamente, o arquivo deve existir.

// o script esta em /home/rodrigo

echo realpath("arquivo.txt") . PHP_EOL; 
// /home/rodrigo/arquivo.txt

echo realpath("docs/arquivo.doc") . PHP_EOL; 
// /home/rodrigo/docs/arquivo.doc

chdir('./docs'); // altera para o diretório corrente para /home/rodrigo/docs/
echo realpath("../arquivo.txt") . PHP_EOL; // .. para voltar um diretório
// /home/rodrigo/arquivo.txt

pathinfo(path, flag=PATHINFO_ALL)

A função pathinfo() retorna várias informações sobre o caminho de um arquivo. Caso uma flag específica seja passada (PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION ou PATHINFO_FILENAME), apenas essa informação será retornada. Se nenhuma flag for informada, a função retorna um array com todas essas informações.

$path_data = pathinfo('/home/rodrigo/arquivo.txt');

print_r($path_data);
// Saída
// Array
// (
//     [dirname] => /home/rodrigo
//     [basename] => arquivo.txt
//     [extension] => txt
//     [filename] => arquivo
// )


$path_basename = pathinfo('/home/rodrigo/arquivo.txt',PATHINFO_BASENAME);
echo $path_basename; // arquivo.txt

Manipulando diretórios

Podemos manipular diretórios utilizando diversas funções do PHP, como mkdir(), rmdir(), chdir(), scandir() e outras, que permitem criar, remover, navegar e listar conteúdos de diretórios.

mkdir(directory, permissions = 0777, recursive = false)

A função mkdir() cria um diretório no caminho especificado em directory. O segundo parâmetro permite definir as permissões (no formato octal) para o diretório. O terceiro parâmetro, recursive, indica se os diretórios pai devem ser criados automaticamente, caso ainda não existam.

mkdir('pasta');
mkdir('minha-pasta', 0777);
mkdir('diretory/rodrigo', 0777, true);

rmdir(path)

A função rmdir() é usada para remover um diretório. É importante lembrar que o diretório deve estar vazio para que a remoção seja bem-sucedida.

rmdir('minha-pasta');

scandir(directory)

A função scandir() retorna um array contendo os arquivos e subdiretórios presentes no diretório especificado em directory.

$files = scandir("docs");

print_r($files);
// Saída
// Array
// (
//     [0] => .
//     [1] => ..
//     [2] => arquivo1.doc
//     [3] => arquivo2.doc
//     [4] => arquivo3.doc
// )

A função scandir() é muito útil quando queremos realizar operações em todos os arquivos de um diretório. Com o uso de recursão, também podemos percorrer subdiretórios. Por exemplo, como a função rmdir() só remove diretórios vazios, podemos utilizar scandir() para listar e apagar todos os arquivos e subdiretórios, e só então remover o diretório principal.

Apagando um diretório recursivamente

function full_rmdir($dir){
    $files = scandir($dir);
    foreach($files as $file){
        if(in_array($file, ['.','..'])){
            continue;
        }
        if(is_dir("$dir/$file")){
            full_rmdir("$dir/$file");
        }else{
            unlink("$dir/$file");
        }
    }
    rmdir($dir);
}

full_rmdir('docs');

Filtrando todos os arquivos por MIME

function filter_mime(string $dir, array $mimes): array
{

    $files = [];
    foreach(scandir($dir) as $file){
        $file_dir = "$dir/$file";
        if(is_file($file_dir) && in_array(mime_content_type($file_dir), $mimes)){
            $files[] = $file_dir;
        }
    }

    return $files;

}

print_r( filter_mime("directory", ['image/png','image/jpeg'] ));

fopen + fgets vs. file_get_contents ?

Agora que entendemos um pouco como manipular arquivos, podemos pensar sobre eficiência. Vimos que é possível ler um arquivo tanto utilizando a combinação de fopen com fgets, quanto com a função file_get_contents. Mas afinal, qual delas devemos utilizar?

A resposta, como quase sempre em programação, é: depende.

Se estivermos lidando com arquivos pequenos ou que precisam ser processados por completo de uma só vez — como ler um arquivo JSON e convertê-lo para array — a função file_get_contents é mais indicada. Ela lê todo o conteúdo do arquivo de forma simples e direta, carregando-o inteiramente na memória.

Por outro lado, se estivermos lidando com arquivos muito grandes, especialmente aqueles que podem ser processados em partes (como arquivos CSV), utilizar file_get_contents pode ser arriscado, pois ele carrega todo o conteúdo do arquivo de uma vez só, o que pode estourar o limite de memória do servidor. Nesse cenário, a combinação de fopen com fgets, que permite a leitura linha por linha, é muito mais eficiente e segura.

Vamos a um exemplo. Suponha que temos um arquivo chamado saidas.csv com 105 MB, contendo dados sobre vendas. Precisamos calcular o total de vendas. Para isso, criaremos duas funções com abordagens diferentes — uma utilizando file_get_contents e outra utilizando fopen com fgets — e então compararemos o uso de memória de cada abordagem.

function processa_arquivo_fgets($file){

    $file = fopen($file,'r');
    
    $total = 0;
    while($line = fgets($file)){
        $data = explode(",",  $line);
        $total += doubleval($data[9]);
    }
    return $total;
}

function processa_arquivo_file_get_contents($file){

    $data = file_get_contents($file);
    
    $total = 0;
    foreach(explode("\n", $data) as $line){
        $data = explode(",",  $line);
        $total += doubleval($data[9]);
    }
    return $total;
}

Agora vamos executar uma das funções e usar a função memory_get_peak_usage() para medir o pico de uso de memória durante a execução. Isso nos ajudará a comparar a eficiência de cada abordagem em termos de consumo de memória.

echo processa_arquivo_fgets('vendas.cvs') . "\n";
echo round(memory_get_peak_usage() / 1024, 2) . " kb";

//Saída do script
// 52468075
// 424.67 kb

Agora, vamos executar a segunda função — que utiliza file_get_contents — para comparar o resultado e o uso de memória.

echo processa_arquivo_file_get_contents('vendas.cvs') . "\n";
echo round(memory_get_peak_usage() / 1024, 2) . " kb";

// Saída do script
// 52468075
// 243892.6 kb

Uma pequena diferença no pico de uso da memória, não? Embora este exemplo seja bastante simples, ele ilustra a ideia. Portanto, sempre que estivermos lidando com arquivos maiores e for possível processá-los em blocos (lendo parte por parte), a abordagem com fopen é a opção mais eficiente e segura em termos de consumo de memória.

Espero que este material tenha proporcionado uma boa visão geral sobre a manipulação de arquivos em PHP. É claro que o PHP oferece muitas outras funções úteis relacionadas a arquivos, e vale a pena consultar a documentação oficial para aprofundar seus conhecimentos e explorar mais possibilidades conforme a necessidade dos seus projetos.

Então era isso T++.