Manipulação de arquivos

Bancos de dados armazenam dados estruturados; arquivos armazenam dados não estruturados — logs, arquivos de configuração, relatórios em CSV, imagens enviadas pelos usuários. Esta lição oferece a você controle total sobre arquivos e diretórios em PHP.

1. Leitura de arquivos

PHP
<?php
// Method 1: file_get_contents() — read an entire file in one line
$content = file_get_contents('hello.txt');
echo $content;

// Method 2: fopen + fread — streamed reading (for large files)
$handle = fopen('hello.txt', 'r');
$content = fread($handle, filesize('hello.txt'));
fclose($handle);

// Method 3: Read line by line (most memory-efficient)
$handle = fopen('data.txt', 'r');
while (($line = fgets($handle)) !== false) {
    echo trim($line) . "<br>";
}
fclose($handle);

// Method 4: file() — read all lines into an array at once
$lines = file('data.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
print_r($lines);
?>
Método Ideal para Memória
file_get_contents() Arquivos pequenos (config, JSON) Todos de uma vez
fopen + fread Arquivos médios Controlado
fopen + fgets Arquivos grandes (logs, CSV) Baixo
file() Arquivos pequenos processados por linha Todos de uma vez

2. Gravação de arquivos

PHP
<?php
// file_put_contents() — write a file in one line
file_put_contents('notes.txt', "Today I learned PHP file handling\n");

// Append mode (third parameter: FILE_APPEND)
file_put_contents('notes.txt', "Now I can append content\n", FILE_APPEND);

// Exclusive lock for writing (prevents concurrent conflicts)
file_put_contents('counter.txt', $count, LOCK_EX);

// fwrite — fine-grained control
$handle = fopen('log.txt', 'a');  // 'a' = append mode
fwrite($handle, date("Y-m-d H:i:s") . " — User logged in\n");
fclose($handle);
?>

▶ Exemplo: Sistema simples de registro de logs

PHP
<?php
class Logger {
    public function __construct(
        private string $logFile
    ) {}
    
    public function info(string $message): void {
        $this->write('INFO', $message);
    }
    
    public function error(string $message): void {
        $this->write('ERROR', $message);
    }
    
    public function warning(string $message): void {
        $this->write('WARNING', $message);
    }
    
    private function write(string $level, string $message): void {
        $time = date("Y-m-d H:i:s");
        $line = "[{$time}] [{$level}] {$message}\n";
        file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
    }
    
    public function getRecent(int $lines = 20): array {
        if (!file_exists($this->logFile)) {
            return [];
        }
        
        $all = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        return array_slice($all, -$lines);
    }
}

$log = new Logger('app.log');
$log->info('App started');
$log->warning('Config file not found, using defaults');
$log->error('Database connection timed out');
$log->info('App finished');

echo "<h3>Recent Logs</h3><pre>" . implode("\n", $log->getRecent(10)) . "</pre>";
?>
▶ Experimente

3. Detecção de arquivos

PHP
<?php
$file = 'test.txt';

// Existence checks
var_dump(file_exists($file));       // bool
var_dump(is_file($file));           // Also check it's a file (not a directory)
var_dump(is_dir($file));            // Check if it's a directory

// Read/Write checks
var_dump(is_readable($file));      // Can it be read?
var_dump(is_writable($file));      // Can it be written to?

// File information
echo filesize($file) . " bytes<br>";  // Size
echo filemtime($file);                 // Last modified time (Unix timestamp)
echo date("Y-m-d H:i:s", filemtime($file)) . "<br>";  // Formatted date
echo pathinfo($file, PATHINFO_EXTENSION);  // txt
?>

▶ Exemplo: Cache de arquivos

PHP
<?php
class FileCache {
    private string $cacheDir;
    
    public function __construct(string $dir = 'cache') {
        $this->cacheDir = $dir;
        if (!is_dir($this->cacheDir)) {
            mkdir($this->cacheDir, 0755, true);
        }
    }
    
    public function get(string $key, int $ttl = 3600): mixed {
        $file = "{$this->cacheDir}/{$key}.cache";
        
        if (!file_exists($file)) return null;
        if (time() - filemtime($file) > $ttl) {
            unlink($file);
            return null;
        }
        
        return unserialize(file_get_contents($file));
    }
    
    public function set(string $key, mixed $value): void {
        $file = "{$this->cacheDir}/{$key}.cache";
        file_put_contents($file, serialize($value), LOCK_EX);
    }
}

$cache = new FileCache();
$cache->set('config', ['app_name' => 'MyBlog', 'version' => '1.0']);
print_r($cache->get('config'));
?>
▶ Experimente

4. Referência rápida sobre operações com arquivos

PHP
<?php
$src = 'source.txt';
$dst = 'backup.txt';

// Copy
copy($src, $dst);

// Rename / Move
rename($src, 'new-name.txt');
rename('/tmp/upload.txt', '/var/www/files/upload.txt');  // Move

// Delete
unlink('old-file.txt');

// Directory operations
mkdir('new-folder', 0755, true);  // true = recursive creation
rmdir('empty-folder');             // Only deletes empty directories

// Traverse a directory
foreach (scandir('uploads') as $item) {
    if ($item !== '.' && $item !== '..') {
        echo "{$item} — " . (is_dir("uploads/{$item}") ? 'Directory' : 'File') . "<br>";
    }
}

// Use glob for pattern-based file search
$images = glob('uploads/*.{jpg,png,gif}', GLOB_BRACE);
echo "Found " . count($images) . " images";
?>

5. Leitura e gravação de arquivos CSV

O CSV é o formato universal para a troca de dados — o Excel consegue abri-lo, e qualquer linguagem de programação consegue lê-lo e gravá-lo:

PHP
<?php
// === Writing CSV ===
$data = [
    ['Name', 'Age', 'City'],
    ['John', 25, 'Beijing'],
    ['Jane', 22, 'Shanghai'],
    ['Bob', 28, 'Guangzhou'],
];

$handle = fopen('users.csv', 'w');
// Write UTF-8 BOM (helps Excel recognize the encoding correctly)
fwrite($handle, "\xEF\xBB\xBF");

foreach ($data as $row) {
    fputcsv($handle, $row);
}
fclose($handle);
echo "CSV file generated ✅<br>";

// === Reading CSV ===
$handle = fopen('users.csv', 'r');
// Skip BOM
fseek($handle, 3);

// Read headers
$headers = fgetcsv($handle);

while (($row = fgetcsv($handle)) !== false) {
    // Use headers as keys
    $item = array_combine($headers, $row);
    echo "{$item['Name']}, {$item['Age']} years old, lives in {$item['City']}<br>";
}
fclose($handle);
?>

▶ Exemplo: Exportação de dados em CSV

PHP
<?php
function exportToCSV(array $data, string $filename): void {
    header('Content-Type: text/csv; charset=utf-8');
    header("Content-Disposition: attachment; filename={$filename}");
    
    $output = fopen('php://output', 'w');
    fwrite($output, "\xEF\xBB\xBF");  // BOM
    
    // Headers
    if (!empty($data)) {
        fputcsv($output, array_keys($data[0]));
    }
    
    // Data
    foreach ($data as $row) {
        fputcsv($output, $row);
    }
    fclose($output);
}
// exportToCSV($usersData, 'users_export.csv');
?>
▶ Experimente

6. Bloqueio de arquivos (prevenção de gravações simultâneas)

PHP
<?php
class Counter {
    private string $file;
    
    public function __construct(string $file = 'counter.dat') {
        $this->file = $file;
        if (!file_exists($this->file)) {
            file_put_contents($this->file, 0);
        }
    }
    
    public function increment(): int {
        $handle = fopen($this->file, 'c+');
        
        // Acquire an exclusive lock (other processes wait)
        if (flock($handle, LOCK_EX)) {
            $count = (int)fread($handle, 100);
            $count++;
            
            // Go back to the beginning of the file
            fseek($handle, 0);
            ftruncate($handle, 0);  // Clear it
            fwrite($handle, (string)$count);
            
            flock($handle, LOCK_UN);  // Unlock
            fclose($handle);
            return $count;
        }
        fclose($handle);
        return -1;
    }
}
?>

❓ Perguntas Frequentes

P: Como faço para escolher entre file_get_contents() e fopen + fgets? R: Use file_get_contents() para arquivos pequenos (<1 MB) — basta uma linha e pronto. Use fgets() para ler linha por linha em arquivos grandes (dezenas de milhares de linhas de log) — ele consome pouca memória. Se você não souber o tamanho, comece com fopen.

P: Os caracteres chineses aparecem distorcidos no Excel? R: Adicione um BOM UTF-8 ("\xEF\xBB\xBF") no início do arquivo CSV. Por padrão, o Excel lê os arquivos usando a codificação local — o BOM indica que o arquivo está no formato UTF-8.

P: O bloqueio de arquivos com flock é realmente necessário? R: Com certeza, quando vários processos leem e gravam o mesmo arquivo simultaneamente. Contadores, caches e logs podem sofrer com condições de corrida, nas quais os valores são lidos depois que outro processo já os modificou — sem bloqueio.

📖 Resumo

📝 Exercícios

  1. Crie um contador de visitantes: a cada atualização da página, a contagem aumenta em 1, sendo armazenada em um arquivo.
  2. Crie um livro de visitas simples: um formulário envia uma mensagem → acrescenta-a a um arquivo → lê e exibe todas as mensagens do arquivo (com registros de data e hora).
  3. Exporte a tabela de usuários para um arquivo CSV (leia os dados do MySQL → gere um arquivo CSV → forneça um link para download).
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%