PHPReading Files

Reading Files

PHP gives you several ways to read a file, and picking the right one depends mostly on how large the file is and whether you need it all in memory at once or can process it piece by piece. This page walks through the three most common approaches — reading a whole file in one call, reading line by line for large files, and pulling the file into an array of lines — plus a look at fgetcsv() and a caveat about reading from remote URLs.

file_get_contents(): the whole file at once

file_get_contents($path) is the simplest way to read a file — it opens the file, reads everything, closes it, and returns the entire contents as a single string. It's the right choice for configuration files, small text files, templates, or anything else you know will comfortably fit in memory.

file-get-contents.php

PHP
<?php

$config = file_get_contents('config.json');

if ($config === false) {
    die('Could not read config.json');
}

$data = json_decode($config, true);
echo $data['app_name'];
Check the return value
`file_get_contents()` returns `false` on failure — a missing file, a permissions issue, or a network error for remote URLs — rather than throwing an exception by default. Comparing the result with `=== false` (not just `if (!$config)`) matters here too, since a file that exists but is genuinely empty returns an empty string, which is falsy but not an error.
fgets() and feof(): reading large files line by line

Loading a multi-gigabyte log file with file_get_contents() would try to allocate the entire file's size in memory at once, which can crash the script or exhaust the server. For files like that, open a handle with fopen() and read one line at a time with fgets(), checking feof() to know when you've reached the end. Only the current line needs to live in memory, no matter how large the file is overall.

line-by-line.php

PHP
<?php

$handle = fopen('access.log', 'r');

if ($handle === false) {
    die('Could not open access.log');
}

$errorCount = 0;

while (!feof($handle)) {
    $line = fgets($handle);

    if ($line !== false && str_contains($line, 'ERROR')) {
        $errorCount++;
    }
}

fclose($handle);

echo "Error lines found: $errorCount";
Error lines found: 3
file(): the whole file as an array of lines

file($path) reads a file and returns an array where each element is one line, including its trailing newline character. It's convenient when you want array operations — count(), array_map(), filtering — on the lines of a moderately sized file, without writing a manual fgets() loop. Pass the FILE_IGNORE_NEW_LINES flag to strip the trailing newline from each element, which is almost always what you want.

file-function.php

PHP
<?php

$lines = file('todo.txt', FILE_IGNORE_NEW_LINES);

foreach ($lines as $number => $line) {
    if ($line === '') {
        continue;
    }
    echo ($number + 1) . ": $line" . PHP_EOL;
}
1: Buy milk
2: Finish report
3: Call the plumber
file() still loads everything into memory
`file()` is convenient, but it builds the entire array of lines in memory up front, just like `file_get_contents()` builds the whole string. For very large files, prefer the `fgets()`/`feof()` loop, or a generator that yields one line at a time, so memory use stays proportional to a single line rather than the whole file.
A quick look ahead: fgetcsv()

When the file you're reading is comma-separated data rather than free-form text, fgetcsv($handle) reads one line and parses it directly into an array of fields, handling quoted values and escaped delimiters correctly — something a hand-rolled explode(',', $line) gets wrong as soon as a field contains a comma inside quotes. The dedicated CSV page covers fgetcsv() and its counterpart fputcsv() in full, including custom delimiters and headers.

fgetcsv-preview.php

PHP
<?php

$handle = fopen('contacts.csv', 'r');
$header = fgetcsv($handle);

$firstRow = fgetcsv($handle);
print_r($firstRow);

fclose($handle);
Reading from remote URLs

file_get_contents() can accept a URL instead of a local path — for example file_get_contents('https://example.com/data.json') — if the allow_url_fopen setting in php.ini is enabled. That's a convenient shortcut, but it comes with real caveats: there's no timeout by default, so a slow or unresponsive server can hang the script; there's no built-in retry or error detail beyond a boolean false; and on some hosts allow_url_fopen is disabled entirely for security reasons. For anything beyond a quick one-off fetch, cURL (or a higher-level HTTP client) gives you timeouts, error codes, and header access that file_get_contents() simply doesn't expose.

  • file_get_contents() — best for small-to-moderate files you need entirely in memory.

  • fgets() + feof() — best for large files processed one line at a time.

  • file() — convenient array-of-lines form, but still loads the whole file.

  • fgetcsv() — parses comma-separated lines into arrays, correctly handling quoted fields.

  • Reading remote URLs with file_get_contents() works but lacks timeouts and detailed error handling.

Tip
When you're not sure how large a file might grow — a log file that accumulates over months, for instance — default to a line-by-line read rather than `file_get_contents()` or `file()`. It costs almost nothing extra for small files, and it means the code won't suddenly break the day the file crosses your server's memory limit.