fopen
Opens a file or URL and returns a stream resource for reading or writing.
fopen(string $filename, string $mode, bool $use_include_path = false, ?resource $context = null): resource|false- Added in PHP 4.0.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$filename | string | Path to the file, or a URL using a registered stream wrapper such as php://memory. |
$mode | string | Access mode: r, r+, w, w+, a, a+, x, x+, c or c+, optionally with b or t appended. |
$use_include_pathoptional | bool= false | Also search the include_path for the file. |
$contextoptional | ?resource= null | A stream context from stream_context_create(), or null for none. |
Return value
resource|falseA file pointer resource on success, or false on failure.
Errors
Emits an E_WARNING and returns false if the file cannot be opened or if the mode is not a valid one; throws a ValueError if filename contains a null byte.
Changelog
- PHP 7.0.16, 7.1.2The 'e' mode option (close-on-exec) was added.
fopen gives you a stream handle instead of a string. Everything else in the f* family — fgets, fread, fwrite, fseek, flock, fputcsv — works on the resource it returns.
Choosing a mode
| Mode | Read | Write | Truncates | Creates | Starts at |
|---|---|---|---|---|---|
| r | yes | no | no | no | start |
| r+ | yes | yes | no | no | start |
| w | no | yes | yes | yes | start |
| w+ | yes | yes | yes | yes | start |
| a | no | yes | no | yes | end |
| x | no | yes | no | fails if exists | start |
| c | no | yes | no | yes | start |
When to reach for it
Use fopen when the file is too big to hold in memory, when you need to read and write the same handle, or when you need a lock. For a small file you just want as a string, file_get_contents is shorter and faster.
What trips people up
Mode 'w' truncates immediately — before any lock, before any check. If you are locking, use 'c' or 'c+'. Mode 'a' always appends at the end regardless of fseek. And always fclose, or at least let the handle fall out of scope; leaked handles exhaust the process limit in long-running workers.
Example
When to use it
- Stream a multi-gigabyte log file line by line with fgets instead of loading it all.
- Open a file with mode 'x' so the call fails if another process already created it.
- Get an in-memory stream with php://memory to build CSV output without touching disk.
Frequently asked questions
What is the difference between fopen modes w and a?
`w` truncates the file to zero bytes on open and writes from the start; `a` keeps the existing content and always writes at the end. Both create the file if it does not exist.
Do I have to call fclose after fopen?
PHP closes the handle when the script ends or the resource goes out of scope, but you should call `fclose` explicitly — it flushes buffers immediately and prevents handle exhaustion in long-running or looping scripts.
Why does fopen return false?
The file does not exist for a read mode, the directory is not writable, permissions deny access, or with mode `x` the file already exists. PHP emits an E_WARNING naming the reason.
More examples
Streaming a large file without loading it
The count comes out as 142 — every seventh request from 7 to 994. Only one line is ever in memory at a time, which is the whole reason to use `fopen` over `file()` on a large log.
<?php
$fh = fopen('big.log', 'w');
for ($i = 1; $i <= 1000; $i++) {
fwrite($fh, "request $i status=" . ($i % 7 === 0 ? 500 : 200) . "\n");
}
fclose($fh);
$errors = 0;
$fh = fopen('big.log', 'r');
while (($line = fgets($fh)) !== false) {
if (str_contains($line, 'status=500')) $errors++;
}
fclose($fh);
echo "errors: $errors of 1000\n";
unlink('big.log');Mode x refuses to clobber an existing file
The first open succeeds and the second dumps `bool(false)`. Mode `x` performs the exists-check and the create as one atomic operation, which makes it a safer lock-file primitive than `file_exists()` followed by a write.
<?php
$first = fopen('once.lock', 'x');
var_dump($first !== false);
fwrite($first, 'owned');
fclose($first);
$second = @fopen('once.lock', 'x'); // already exists
var_dump($second);
unlink('once.lock');An in-memory stream needs no disk at all
The stream behaves exactly like a file handle — write, rewind, read back — but nothing is created on disk. This is the usual way to build CSV or fixture data for functions that insist on a resource.
<?php
$fh = fopen('php://memory', 'r+');
fwrite($fh, "id,name\n");
fwrite($fh, "1,Ada\n");
fwrite($fh, "2,Grace\n");
rewind($fh);
echo stream_get_contents($fh);
echo 'bytes: ', ftell($fh), "\n";
fclose($fh);
Discussion