fread

Reads up to a given number of bytes from an open file or stream handle.

Signature
fread(resource $stream, int $length): string|false
  • Added in PHP 4

Parameters

ParameterTypeDescription
$streamresourceAn open stream handle, typically returned by fopen(), fsockopen() or tmpfile().
$lengthintThe maximum number of bytes to read. Must be greater than 0.

Return value

string|falseThe bytes read as a string, or false on failure. An empty string is returned when the pointer is already at end of file.

Errors

Throws a ValueError if $length is less than 1, and a TypeError if $stream is not an open stream resource.

fread pulls a fixed number of bytes off an open stream and returns them as a string. It is the binary-safe counterpart to fgets: it does not look for line endings, so it is the correct tool for images, archives, fixed-width records and any file you want to walk in chunks rather than load whole.

When to reach for it

Reach for it when the file is too large to hold in memory, when you only need the first few bytes (a magic number, a header), or when you are reading from something that is not a plain file at all — a pipe, a socket, php://stdin.

What trips people up

The classic mistake is treating one call as one complete read. For a plain local file, fread($fp, filesize($file)) does return everything. For any other stream it does not: the engine stops after a single buffer fill, usually 8192 bytes, and returns short. Correct code loops:

$data = '';
while (!feof($fp)) {
    $data .= fread($fp, 8192);
}

The second mistake is checking the result with a plain falsy test. At end of file fread returns '', which is falsy but not an error, so use === false for failure and feof() for exhaustion. If you simply want the whole file as a string, file_get_contents is shorter and faster.

Example

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

When to use it

  • Stream a large CSV or log file to the browser in 8 KB chunks without exhausting memory_limit.
  • Read the first few bytes of an upload to sniff its real file type instead of trusting the extension.
  • Copy a binary file byte-for-byte while computing a running checksum.

Frequently asked questions

What is the difference between fread and file_get_contents?

file_get_contents opens the file, reads all of it into a string and closes it in one call, while fread reads a bounded number of bytes from a handle you manage yourself. Use file_get_contents for small files and fread when you need chunking, a shared handle, or a non-file stream.

Why does fread return fewer bytes than I asked for?

For anything other than a plain local file, fread stops after one internal buffer fill (usually 8192 bytes) or when a network packet arrives, so short reads are normal. Loop with feof() and append until the stream is exhausted.

How do I read a whole file with fread?

Use fread($fp, filesize($file)) for a plain local file, or loop with while (!feof($fp)) { $data .= fread($fp, 8192); } for anything else. stream_get_contents($fp) does the same loop for you in one call.

More examples

Reading a large file in chunks

The file is 50 bytes, so the loop runs four times: three full 16-byte reads and one 2-byte read, then feof() ends it. This is the pattern you need for anything that is not a plain local file, because a single fread can always come back short.

Example · php
<?php
$file = "chunks.txt";
file_put_contents($file, str_repeat("ab", 25));

$fp = fopen($file, "rb");
$chunks = 0;
while (!feof($fp)) {
    $buffer = fread($fp, 16);
    if ($buffer === false) { break; }
    $chunks++;
}
fclose($fp);
echo "read $chunks chunks of 16 bytes\n";
unlink($file);

Sniffing a file header

Only 8 bytes are read, so the size of the rest of the file is irrelevant. The output shows the PNG magic number matching and its hex form; fread is binary-safe, so the null and control bytes survive intact.

Example · php
<?php
$file = "header.bin";
file_put_contents($file, "\x89PNG\r\n\x1a\n" . str_repeat("\0", 20));

$fp = fopen($file, "rb");
$magic = fread($fp, 8);
fclose($fp);

var_dump($magic === "\x89PNG\r\n\x1a\n");
echo bin2hex($magic), "\n";
unlink($file);

fread at end of file returns an empty string

The first call returns "hi", the second returns "" because the pointer is already at the end. The empty string is not an error, which is why an if (!$data) test would wrongly report failure and why feof() is the right end-of-stream check.

Example · php
<?php
$fp = fopen("php://memory", "r+b");
fwrite($fp, "hi");
rewind($fp);

$a = fread($fp, 10);
$b = fread($fp, 10);
var_dump($a, $b, $b === false, feof($fp));
fclose($fp);

Discussion

  • Be the first to comment on this lesson.