file

Reads an entire file into an array, with one element per line.

Signature
file(string $filename, int $flags = 0, ?resource $context = null): array|false
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$filenamestringPath to the file.
$flagsoptionalint= 0A bitmask of FILE_USE_INCLUDE_PATH, FILE_IGNORE_NEW_LINES, FILE_SKIP_EMPTY_LINES and FILE_NO_DEFAULT_CONTEXT.
$contextoptional?resource= nullA stream context created with stream_context_create().

Return value

array|falseAn array with one element per line of the file, or false on failure.

Errors

Emits E_WARNING and returns false when the file cannot be opened. As of PHP 8.3 a ValueError is thrown for invalid flags.

Changelog

  • PHP 8.3.0A ValueError is thrown for any invalid value of flags, instead of the value being silently ignored.

file() is the one-liner for "give me the lines of this file". It opens, reads, splits and closes in a single call, and the result is a plain indexed array you can foreach, array_filter or count.

The flags

  • FILE_IGNORE_NEW_LINES — drop the line ending from each element. Almost always what you want.
  • FILE_SKIP_EMPTY_LINES — omit blank lines.
  • FILE_USE_INCLUDE_PATH — also look for the file on the include path.

Combine them with |.

When not to reach for it

The whole file lands in memory, and an array of short strings costs considerably more than the file's byte size — every element carries its own zval and string header. On a 500 MB log that is a fatal memory error. Switch to fopen() plus a fgets() loop the moment the file could be large or is attacker-controlled in size.

Also note the newlines: without FILE_IGNORE_NEW_LINES every element except possibly the last ends in \n, and on a Windows file in \r\n. Comparisons against the raw elements will fail.

Since PHP 8.3 an invalid flag value throws a ValueError rather than being silently ignored — passing a constant that does not belong here, such as FILE_APPEND, now fails loudly instead of doing nothing.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Load a small allow-list or blocklist of domains into an array in one call
  • Number and display the lines of a short config or template file
  • Parse a key=value settings file with explode() after splitting on lines
  • Count matching lines in a modest log file with array_filter()

Frequently asked questions

What is the difference between file and file_get_contents?

file() returns an array with one element per line; file_get_contents() returns the whole file as a single string. Both load everything into memory, so neither is suitable for very large files.

How do I remove the newline characters from file()?

Pass FILE_IGNORE_NEW_LINES as the second argument. Combine it with FILE_SKIP_EMPTY_LINES using | when you also want blank lines dropped.

Is file safe to use on large files?

No. The entire file becomes an array in memory, and per-element overhead makes the array larger than the file itself, so a big log will exhaust memory_limit. Use fopen() with an fgets() loop instead.

More examples

Numbering and filtering log lines

Array keys are zero-based line offsets, so display numbers need the + 1. array_filter() preserves keys, which is why array_values() is wrapped around it — otherwise the single match would come back with key 2 and json_encode() would render it as an object rather than a list.

Example · php
<?php
file_put_contents("app.log", "boot\nwarn: slow\nerror: 500\ndone\n");

$lines = file("app.log", FILE_IGNORE_NEW_LINES);
foreach ($lines as $i => $line) {
    printf("%3d %s\n", $i + 1, $line);
}

$errors = array_values(array_filter($lines, fn($l) => str_starts_with($l, "error")));
print_r($errors);

unlink("app.log");

Parsing a key=value config

The two flags together give clean, blank-free lines so the loop only has to skip comments. The third argument to explode() caps the split at two parts, so a value that itself contains an equals sign survives intact — dropping it is a common source of truncated passwords and DSNs.

Example · php
<?php
file_put_contents("app.ini", "host=localhost\nport=5432\n\n# a comment\nuser=admin\n");

$config = [];
foreach (file("app.ini", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
    if ($line === "" || $line[0] === "#") {
        continue;
    }
    [$key, $value] = explode("=", $line, 2);
    $config[$key] = $value;
}
print_r($config);

unlink("app.ini");

Why FILE_SKIP_EMPTY_LINES needs its partner

The first two counts are both 3. On its own FILE_SKIP_EMPTY_LINES sees the blank line as the one-character string "\n", which is not empty, so nothing is skipped. Only with FILE_IGNORE_NEW_LINES also set does the line become genuinely empty and the count drop to 2.

Example · php
<?php
file_put_contents("gaps.txt", "a\n\nb\n");

var_dump(count(file("gaps.txt")));
var_dump(count(file("gaps.txt", FILE_SKIP_EMPTY_LINES)));
var_dump(count(file("gaps.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)));

unlink("gaps.txt");

Discussion

  • Be the first to comment on this lesson.