Signature
fprintf(resource $stream, string $format, mixed ...$values): intPurpose
fprintf() builds a string from a format template and a list of values, then writes that string to a stream you supply. It is the stream-oriented sibling of printf() (which writes to output) and sprintf() (which returns the string). Use it when formatted text must go to a particular resource: a log handle, a socket, a temporary buffer or an in-memory stream.
Signature
Parameters
$stream: a writable stream resource, usually fromfopen(). There is no default; it is required.$format: the template. Ordinary characters are copied unchanged, and each conversion specification such as%dor%sconsumes a value. The general shape is%[argnum$][flags][width][.precision]specifier....$values: zero or more values used by the conversion specifications. There is no default list.
Useful pieces of the format language:
- Specifiers:
dfor signed integers,sfor strings,fandFfor floats (frespects the locale,Fdoes not),xandXfor hexadecimal,bfor binary,ofor octal,efor scientific notation, and%%for a literal percent sign. - Flags:
-left-justifies,+forces a sign on positive numbers,0pads with zeros, and'cpads with the characterc. - Width sets a minimum field size. Precision, written as
.n, sets decimals for floats or a maximum length for strings. argnum$such as%2$sselects a value by position, so the same value can be reused or the order changed.
Return value and failure cases
The function returns an int: the length of the string that was written, counted in bytes. Since PHP 8.0 it no longer returns false on failure. Problems with the format itself are reported by exceptions:
ArgumentCountErrorwhen fewer values are supplied than the format needs.ValueErrorwhen the width or precision is negative or larger thanPHP_INT_MAX, or when the argument count is zero.
Example 1: zero-padded integers
The examples use php://memory, so nothing touches the disk. After writing, rewind() moves the pointer back so the contents can be read.
$stream = fopen('php://memory', 'w+');
$length = fprintf($stream, '%04d-%02d-%02d', 2005, 5, 6);
rewind($stream);
echo json_encode([$length, stream_get_contents($stream)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
fclose($stream);[10,"2005-05-06"]
The date is ten bytes long, and the return value confirms it.
Example 2: money, padding and flags
$stream = fopen('php://memory', 'w+');
$total = 68.75 + 54.35;
$a = fprintf($stream, "%01.2f\n", $total);
$b = fprintf($stream, "%'*10s|%-8s|%+d\n", 'abc', 'left', 5);
rewind($stream);
echo stream_get_contents($stream);
echo $a, ' ', $b, "\n";
fclose($stream);123.10 *******abc|left |+5 7 23
The %01.2f directive always shows two decimals, so a sum that PHP would echo as 123.1 is written as 123.10. The second call shows a custom padding character, left justification and an explicit plus sign. Each return value includes the trailing newline.
Example 3: positional arguments
$stream = fopen('php://memory', 'w+');
$length = fprintf($stream, '%2$s has %1$d items (%3$05.1f%%)', 3, 'Cart', 42.456);
rewind($stream);
echo json_encode([$length, stream_get_contents($stream)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
fclose($stream);[25,"Cart has 3 items (042.5%)"]
Values are passed as 3, 'Cart', 42.456, but the template picks them out of order with %2$s, %1$d and %3$05.1f. The final %% writes a literal percent sign.
Edge cases
- The return value counts bytes. A string such as
éin UTF-8 occupies two bytes, so the count can exceed the number of visible characters. - Width and precision on
salso operate on bytes, so padding or truncating multibyte text may split a character. - The
cspecifier ignores width and padding. - Values are coerced to suit the specifier, so
%dapplied to a numeric string converts it to an integer, and%dapplied to a float drops the fractional part. - Once you use positional
argnum$forms, keep the numbering consistent so the template remains readable. - Using
*for width or precision consumes an extra integer value before the formatted one.
Common mistakes
- Forgetting
rewind()when reading back. After writing to aw+memory stream the pointer is at the end, so reading immediately returns an empty string. - Passing too few values. The format needs one value per non-positional directive; a shortfall throws
ArgumentCountError. - Writing a bare percent sign. A literal
%must be written as%%, otherwise the next characters are read as a directive. - Assuming the return value is a success flag. It is the written length, not a boolean.
- Expecting locale-independent floats from
%f. Use%Fwhen the decimal separator must never change with the locale. - Using an unsuitable stream. The resource must be open and writable, so pick an appropriate mode with
fopen().
Related functions
printf()writes a formatted string to output.sprintf()returns the formatted string instead of writing it.vfprintf()accepts the values as an array.vprintf()andvsprintf()are the array-based output and string versions.number_format()groups thousands and is handy for display amounts.fscanf()andsscanf()parse input according to a format.
Recap
fprintf() formats like sprintf() but sends the text to a stream and returns the byte length. Learn the directive pattern %[argnum$][flags][width][.precision]specifier, remember %% for a literal percent sign, and expect ArgumentCountError or ValueError for malformed calls.
Tested examples
$stream = fopen('php://memory', 'w+');
$length = fprintf($stream, '%04d-%02d-%02d', 2005, 5, 6);
rewind($stream);
echo json_encode([$length, stream_get_contents($stream)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
fclose($stream);[10,"2005-05-06"]
$stream = fopen('php://memory', 'w+');
$total = 68.75 + 54.35;
$a = fprintf($stream, "%01.2f\n", $total);
$b = fprintf($stream, "%'*10s|%-8s|%+d\n", 'abc', 'left', 5);
rewind($stream);
echo stream_get_contents($stream);
echo $a, ' ', $b, "\n";
fclose($stream);123.10 *******abc|left |+5 7 23
$stream = fopen('php://memory', 'w+');
$length = fprintf($stream, '%2$s has %1$d items (%3$05.1f%%)', 3, 'Cart', 42.456);
rewind($stream);
echo json_encode([$length, stream_get_contents($stream)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
fclose($stream);[25,"Cart has 3 items (042.5%)"]