PHP's fopen(), fgets(), and fclose() functions open a file handle and read data incrementally instead of loading the entire file into memory at once. Streaming is essential when processing large CSV imports, server access logs, or multi-megabyte exports.
Pass a mode string to fopen() to tell the operating system how your script plans to access the file.
| Mode | Purpose | Pointer Position |
|---|---|---|
'r' |
Read only (file must exist) | Start of file |
'r+' |
Read and write (file must exist) | Start of file |
'rb' |
Read only in binary mode | Start of file |
Always wrap fopen() checks with === false and close the handle inside a try / finally block so open file descriptors never leak if an exception occurs mid-read.
<?php
declare(strict_types=1);
function countErrorsInLog(string $path): int
{
$handle = fopen($path, 'rb');
if ($handle === false) {
throw new RuntimeException("Unable to open file: {$path}");
}
$errorCount = 0;
try {
while (($line = fgets($handle)) !== false) {
if (str_contains($line, '[ERROR]')) {
$errorCount++;
}
}
} finally {
fclose($handle);
}
return $errorCount;
}
fgetcsv()Avoid splitting CSV lines with explode(',', $line) because quoted fields containing commas ("Dhaka, BD") will break. Use fgetcsv() instead, which handles quoted columns and escaped characters properly.
<?php
$csv = fopen('php://temp', 'r+b');
fwrite($csv, "sku,name,price
KB-01,"Mechanical Keyboard, RGB",89.50
");
rewind($csv);
$headers = fgetcsv($csv);
while (($row = fgetcsv($csv)) !== false) {
$record = array_combine($headers, $row);
print_r($record);
}
fclose($csv);
while (!feof($handle)) without checking fgets() !== false: At the end of a file, feof() does not become true until a read fails, causing one extra loop with false. Loop directly on while (($line = fgets($handle)) !== false).fclose($handle): Leaving open handles inside long-running queue workers hits OS open-file limits.'b' flag on binary files: Always add 'b' (e.g. 'rb') so Windows does not translate newline bytes unexpectedly.fgets() over file_get_contents()?Use file_get_contents() for small files under a few megabytes. Switch to fopen() + fgets() whenever file sizes could grow large or unpredictable.
fread($handle, filesize($path)) do?fread() reads an exact number of raw bytes from an open handle, which is useful for reading fixed binary headers or chunked file transfers.
SplFileObject in PHP?SplFileObject is an object-oriented wrapper around file handles that implements Iterator, allowing clean foreach loops over lines without manual fgets() calls.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.