Reading and writing files: file_get_contents, file_put_contents, fopen/fread/fwrite
Concept
PHP provides multiple ways to read file contents, each suited to different use cases. The primary distinction is between reading a whole file at once (simple but memory-intensive) versus reading incrementally via a file handle (memory-efficient for large files).
file_get_contents(string $filename): One-liner for reading entire file into a string. Handles local files and URLs (with allow_url_fopen). Returns false on failure. For most uses, this is the right choice — fast, simple, and PHP internally buffers efficiently.
file(string $filename): Reads entire file into an array of lines, preserving line endings unless FILE_IGNORE_NEW_LINES is passed. Convenient for line-by-line processing of small files.
fopen() / fread() / fclose(): Low-level file handle operations. Essential when: the file is large (read in chunks), you need to seek within the file, or you need both read and write access. Always close the handle with fclose() — PHP closes it at script end, but relying on that delays resource release.
SplFileObject: OOP wrapper around a file handle. Supports line iteration, fgets(), fgetcsv(), fseek(), and more. Useful when you want an iterator over file lines.
readfile(string $filename): Reads a file and writes it directly to output buffer. Returns the number of bytes output. Useful for sending file downloads — more efficient than echo file_get_contents(...) because it streams directly.
Code Example
<?php
declare(strict_types=1);
// file_get_contents — simple whole-file read
$content = file_get_contents('/etc/hosts');
if ($content === false) {
throw new \RuntimeException("Failed to read /etc/hosts");
}
// file() — array of lines
$lines = file('/var/log/app.log', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
echo $line . "\n";
}
// fopen/fread — chunked reading for large files
$handle = fopen('/path/to/large-file.csv', 'r');
if ($handle === false) {
throw new \RuntimeException("Cannot open file");
}
try {
while (!feof($handle)) {
$chunk = fread($handle, 8192); // read 8KB at a time
if ($chunk === false) break;
// process $chunk
}
} finally {
fclose($handle); // always close
}
// fgets — read line by line
$handle = fopen('/var/log/app.log', 'r');
try {
while (($line = fgets($handle)) !== false) {
echo trim($line) . "\n";
}
} finally {
fclose($handle);
}
// SplFileObject — OOP file iteration
$file = new \SplFileObject('/path/to/data.csv');
$file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
foreach ($file as $row) {
[$name, $email, $age] = $row;
// process each CSV row
}
// readfile — stream file to output (for downloads)
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="report.csv"');
header('Content-Length: ' . filesize('/path/to/report.csv'));
readfile('/path/to/report.csv'); // streams directly to output