fwrite

(PHP 4, PHP 5, PHP 7, PHP 8)

fwrite写入文件(可安全用于二进制文件)

说明

fwrite(resource $stream, string $data, ?int $length = null): int|false

fwrite()data 的内容写入 文件指针 stream 处。

参数

stream

文件系统指针,是典型地由 fopen() 创建的 resource(资源)。

data

要写入的字符串。

length

如果 lengthint,当写入了 length 个字节或者写完了 string 以后,写入就会停止,看先碰到哪种情况。

返回值

fwrite() 返回写入的字符数, 或者在失败时返回 false

错误/异常

fwrite() 失败时会引发 E_WARNING

更新日志

版本 说明
8.0.0 现在 length 可以为 null。

示例

示例 #1 简单的 fwrite() 示例

<?php
$filename
= 'test.txt';
$somecontent = "Add this to the file\n";

// 首先确认文件存在且可写。
if (is_writable($filename)) {

// 在示例中,使用追加模式打开 $filename。
// 文件指针应该在文件的末尾,
// 那就是使用 fwrite() 写入 $somecontent 的地方。
if (!$fp = fopen($filename, 'a')) {
echo
"Cannot open file ($filename)";
exit;
}

// 将 $somecontent 写入到打开的文件。
if (fwrite($fp, $somecontent) === FALSE) {
echo
"Cannot write to file ($filename)";
exit;
}

echo
"Success, wrote ($somecontent) to file ($filename)";

fclose($fp);

} else {
echo
"The file $filename is not writable";
}
?>

注释

注意:

Writing to a network stream may end before the whole string is written. Return value of fwrite() may be checked:

<?php
function fwrite_stream($fp, $string) {
for (
$written = 0; $written < strlen($string); $written += $fwrite) {
$fwrite = fwrite($fp, substr($string, $written));
if (
$fwrite === false) {
return
$written;
}
}
return
$written;
}
?>

注意:

在区分二进制文件和文本文件的系统上(如 Windows) 打开文件时,fopen() 函数的 mode 参数要加上 'b'。

注意:

如果 streamfopen() 追加模式,fwrite() 是原子操作(unless the size of data exceeds the filesystem's block size, on some platforms, and as long as the file is on a local filesystem)。也就是说,在调用 fwrite() 之前不需要 flock() 资源;所有的数据都将会不间断写入。

注意:

如果向文件指针写入两次,然后数据将追加到文件内容的末尾:

<?php
$fp
= fopen('data.txt', 'w');
fwrite($fp, '1');
fwrite($fp, '23');
fclose($fp);

// “data.txt”的内容是 123 而不是 23!
?>

参见

  • fread() - 读取文件(可安全用于二进制文件)
  • fopen() - 打开文件或者 URL
  • fsockopen() - 打开 Internet 或者 Unix 套接字连接
  • popen() - 打开进程文件指针
  • file_get_contents() - 将整个文件读入一个字符串
  • pack() - 将数据打包成二进制字符串

添加备注

用户贡献的备注 22 notes

up
107
nate at frickenate dot com
14 years ago
After having problems with fwrite() returning 0 in cases where one would fully expect a return value of false, I took a look at the source code for php's fwrite() itself. The function will only return false if you pass in invalid arguments. Any other error, just as a broken pipe or closed connection, will result in a return value of less than strlen($string), in most cases 0.

Therefore, looping with repeated calls to fwrite() until the sum of number of bytes written equals the strlen() of the full value or expecting false on error will result in an infinite loop if the connection is lost.

This means the example fwrite_stream() code from the docs, as well as all the "helper" functions posted by others in the comments are all broken. You *must* check for a return value of 0 and either abort immediately or track a maximum number of retries.

Below is the example from the docs. This code is BAD, as a broken pipe will result in fwrite() infinitely looping with a return value of 0. Since the loop only breaks if fwrite() returns false or successfully writes all bytes, an infinite loop will occur on failure.

<?php
// BROKEN function - infinite loop when fwrite() returns 0s
function fwrite_stream($fp, $string) {
for (
$written = 0; $written < strlen($string); $written += $fwrite) {
$fwrite = fwrite($fp, substr($string, $written));
if (
$fwrite === false) {
return
$written;
}
}
return
$written;
}
?>
up
3
divinity76 at gmail dot com
3 years ago
if you need a function that writes all data, maybe try

<?php

/**
* writes all data or throws
*
* @param mixed $handle
* @param string $data
* @throws \RuntimeException when fwrite returned <1 but still more data to write
* @return void
*/
/*private static*/
function fwrite_all($handle, string $data): void
{
$original_len = strlen($data);
if (
$original_len > 0) {
$len = $original_len;
$written_total = 0;
for (;;) {
$written_now = fwrite($handle, $data);
if (
$written_now === $len) {
return;
}
if (
$written_now < 1) {
throw new
\RuntimeException("could only write {$written_total}/{$original_len} bytes!");
}
$written_total += $written_now;
$data = substr($data, $written_now);
$len -= $written_now;
// assert($len > 0);
// assert($len === strlen($data));
}
}
}
up
3
niklesh at example dot com
4 years ago
$handles can also be used to output in console like below example

fwrite(STDOUT, "Console Output");
up
5
Anonymous
8 years ago
// you want copy dummy file or send dummy file
// it is possible to send a file larger than 4GB and write without FSEEK used is limited by PHP_INT_MAX. it works on a system 32-bit or 64-bit
// fwrite and fread non pas de limite de position du pointeur

<?php

$gfz
= filesize_dir("d:\\starwars.mkv"); // 11,5GB
echo 'Z:',$gfz,PHP_EOL;

$fz = fopen('d:\\test2.mkv', 'wb');
$fp = fopen('d:\\starwars.mkv', 'rb');
echo
PHP_EOL;
$a = (float) 0;
while((
$l=fread($fp, 65536))) {
fwrite($fz, $l);
if((
$a+=65536)%5) echo "\r", '>', $a, ' : ' , $gfz;
}

fclose($fp);
fclose($fz);

// test2.mkv' is 11,5GB

function filesize_dir($file) {
exec('dir ' . $file, $inf);
$size_raw = $inf[6];
$size_exp = explode(" ",$size_raw);
$size_ext = $size_exp[19];
$size_int = (float) str_replace(chr(255), '', $size_ext);
return
$size_int;
}
?>
up
5
Chris Blown
21 years ago
Don't forget to check fwrite returns for errors! Just because you successfully opened a file for write, doesn't always mean you can write to it.

On some systems this can occur if the filesystem is full, you can still open the file and create the filesystem inode, but the fwrite will fail, resulting in a zero byte file.
up
5
dharris dot nospam at removethispart dot drh dot net
16 years ago
Some people say that when writing to a socket not all of the bytes requested to be written may be written. You may have to call fwrite again to write bytes that were not written the first time. (At least this is how the write() system call in UNIX works.)

This is helpful code (warning: not tested with multi-byte character sets)

function fwrite_with_retry($sock, &$data)
{
$bytes_to_write = strlen($data);
$bytes_written = 0;

while ( $bytes_written < $bytes_to_write )
{
if ( $bytes_written == 0 ) {
$rv = fwrite($sock, $data);
} else {
$rv = fwrite($sock, substr($data, $bytes_written));
}

if ( $rv === false || $rv == 0 )
return( $bytes_written == 0 ? false : $bytes_written );

$bytes_written += $rv;
}

return $bytes_written;
}

Call this like so:

$rv = fwrite_with_retry($sock, $request_string);

if ( ! $rv )
die("unable to write request_string to socket");
if ( $rv != strlen($request_string) )
die("sort write to socket on writing request_string");
up
2
synnus at gmail dot com
8 years ago
// you want copy dummy file or send dummy file
// it is possible to send a file larger than 4GB and write without FSEEK used is limited by PHP_INT_MAX. it works on a system 32-bit or 64-bit
// fwrite and fread non pas de limite de position du pointeur

<?php

$gfz
= filesize_dir("d:\\starwars.mkv"); // 11,5GB
echo 'Z:',$gfz,PHP_EOL;

$fz = fopen('d:\\test2.mkv', 'wb');
$fp = fopen('d:\\starwars.mkv', 'rb');
echo
PHP_EOL;
$a = (float) 0;
while((
$l=fread($fp, 65536))) {
fwrite($fz, $l);
if((
$a+=65536)%5) echo "\r", '>', $a, ' : ' , $gfz;
}

fclose($fp);
fclose($fz);

// test2.mkv' is 11,5GB

function filesize_dir($file) {
exec('dir ' . $file, $inf);
$size_raw = $inf[6];
$size_exp = explode(" ",$size_raw);
$size_ext = $size_exp[19];
$size_int = (float) str_replace(chr(255), '', $size_ext);
return
$size_int;
}
?>
up
3
Anonymous
15 years ago
If you write with the pointer in the middle of a file, it overwrites what's there rather than shifting the rest of the file along.
up
2
chedong at hotmail dot com
21 years ago
the fwrite output striped the slashes if without length argument given, example:

<?php
$str
= "c:\\01.txt";
$out = fopen("out.txt", "w");
fwrite($out, $str);
fclose($out);
?>

the out.txt will be:
c:^@1.txt
the '\\0' without escape will be '\0' ==> 0x00.

the correct one is change fwrite to:
fwrite($out, $str, strlen($str));
up
3
php at biggerthanthebeatles dot com
21 years ago
Hope this helps other newbies.

If you are writing data to a txt file on a windows system and need a line break. use \r\n . This will write hex OD OA.

i.e.
$batch_data= "some data... \r\n";
fwrite($fbatch,$batch_data);

The is the equivalent of opening a txt file in notepad pressing enter and the end of the line and saving it.
up
0
synnus at gmail dot com
3 years ago
<?php
/*
Write to offset with positive offset

PHP_INT_MIN / PHP_INT_MAX 32-bit PHP: -2,147,483,648 to +2,147,483,647
PHP_INT_MIN / PHP_INT_MAX 64-bit PHP: -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807

File_writing 32bit 0 -> 4 294 967 295
File_writing 64bit 0 -> 18 446 744 073 709 551 615

$handel = fopen( myfilname );
$t_f_max is max file size in BYTE ex: 19998
$offset is position in offset BYTE ex : 19995
$bin your binary data you want write

Work in 32bit and 64bit
*/

function File_writing($handel,$t_f_max,$offset,$bin) {
(
$offset > PHP_INT_MAX) ? fseek($handel,-($t_f_max-$offset),SEEK_END) : fseek($handel,$offset,SEEK_SET);
fwrite($handel,$bin);
return
$offset;
}

?>
up
0
2184364 at gmail dot com
5 years ago
//fwrite writes over, i.e. this example (win) may be misleading:

$file = 'e:/1.txt';

file_put_contents($file, 'hello'.chr(1).'0df6ac'.chr(0));

$fp = fopen($file, 'r+b');

$str = fread($fp, filesize($file));

$str = strtr($str, [chr(0)=>'']);
echo $str.PHP_EOL;//hello0df6ac

fseek($fp, 0);//указатель в начало
fwrite($fp, $str);

fclose($fp);

//add ftruncate ($ fp, 0);
//this will overwrite the file:

file_put_contents($file, 'hello'.chr(1).'0df6ac'.chr(0));

$fp = fopen($file, 'r+b');

$str = fread($fp, filesize($file));

$str = strtr($str, [chr(0)=>'']);
echo $str.PHP_EOL;//hello0df6ac

ftruncate ($ fp, 0);
fseek($fp, 0);//указатель в начало
fwrite($fp, $str);

fclose($fp);
up
-1
Jon Haynes
13 years ago
Be careful of using reserved Windows filenames in fwrite operations.

<?php
$fh
= fopen('prn.txt', 'w');
fwrite($fh, 'wtf?');
echo
'done' . PHP_EOL;
?>

The above script will hang (tested on Windows 7) before it can echo 'done'.

This is due to another 'feature' of our favourite operating system where filenames like prn.xxx, con.xxx, com1.xxx and aux.xxx (with xxx being any filename extension) are Windows reserved device names. Attempts to create/read/write to these files hangs the interpreter.
up
-1
qrworld.net
10 years ago
Here you have a function found on the website http://softontherocks.blogspot.com/2014/11/funcion-para-escribir-en-un-fichero-log.html with an example of how to make a log file.

The function is this:

function writeLog($data) {
list($usec, $sec) = explode(' ', microtime());
$datetime = strftime("%Y%m%d %H:%M:%S",time());
$msg = "$datetime'". sprintf("%06s",intval($usec*1000000)).": $data";
$save_path = 'foo.txt';
$fp = @fopen($save_path, 'a'); // open or create the file for writing and append info
fputs($fp, "$msg\n"); // write the data in the opened file
fclose($fp); // close the file
}
up
-2
chill at cuna dot org
20 years ago
In PHP 4.3.7 fwrite returns 0 rather than false on failure.
The following example will output "SUCCESS: 0 bytes written" for existing file test.txt:

$fp = fopen("test.txt", "rw");
if (($bytes_written = fwrite($fp, "This is a test")) === false) {
echo "Unable to write to test.txt\n\n";
} else {
echo "SUCCESS: $bytes_written bytes written\n\n";
}
up
-4
dominic at varspool dot com
10 years ago
Note that the optional $length argument is expected to be an int, and cannot be skipped by passing null.

That is, `fwrite($handle, $string, null)` is treated as `fwrite($handle, $string, 0)`, and will write zero bytes, not the whole string.
up
-3
james at nicolson dot biz
19 years ago
I could'nt quite get MKP Dev hit counter to work.... this is how I modified it
<?
function hitcount()
{
$file = "counter.txt";
if ( !
file_exists($file)){
touch ($file);
$handle = fopen ($file, 'r+'); // Let's open for read and write
$count = 0;

}
else{
$handle = fopen ($file, 'r+'); // Let's open for read and write
$count = fread ($handle, filesize ($file));
settype ($count,"integer");
}
rewind ($handle); // Go back to the beginning
/*
* Note that we don't have problems with 9 being fewer characters than
* 10 because we are always incrementing, so we will always write at
* least as many characters as we read
**/
fwrite ($handle, ++$count); // Don't forget to increment the counter
fclose ($handle); // Done

return $count;
}
?>
up
-5
Jake Roberts
21 years ago
Use caution when using:

$content = fread($fh, filesize($fh)) or die "Error Reading";

This will cause an error if the file you are reading is zero length.

Intead use:

if ( false === fread($fh, filesize($fh)) ) die "Error Reading";

Thus it will be successful on reading zero bytes but detect and error returned as FALSE.
up
-5
bluevd at gmail dot com
19 years ago
Watch out for mistakes in writting a simple code for a hit counter:
<?php
$cont
=fopen('cont.txt','r');
$incr=fgets($cont);
//echo $incr;
$incr++;
fclose($cont);
$cont=fopen('cont.txt','a');
fwrite($cont,$incr);
fclose($cont);
?>

Why? notice the second fopen -> $cont=fopen('cont.txt','a');
it opens the file in writting mode (a). And when it ads the incremented
value ( $incr ) it ads it ALONG the old value... so opening the counter
page about 5 times will make your hits number look like this
012131214121312151.21312141213E+ .... you get the piont.
nasty, isn't it? REMEMBER to open the file with the 'w' mode (truncate
the file to 0). Doing this will clear the file content and it will make sure that
your counter works nice. This is the final code

<?php
$cont
=fopen('cont.txt','r');
$incr=fgets($cont);
//echo $incr;
$incr++;
fclose($cont);
$cont=fopen('cont.txt','w');
fwrite($cont,$incr);
fclose($cont);
?>

Notice that this work fine =)
XU (alias Iscu Andrei)
up
-4
ceo at l-i-e dot com
16 years ago
If you are trying to write binary/structured data (e.g., a 4-byte sequence for an (int)) to a file, you will need to use:
http://php.net/pack
up
-4
David Spector
8 years ago
This may save you time: note that neither "binary-safe file write" nor the use of b mode in fopen mean that fwrite can write binary. It can only write strings (or a single character). For example, attempting to write the byte 0x1 using fwrite results in writing the byte value 0x31.

If you wish to write binary values (bits, bytes, integers, etc.), use a statement like fprintf($Res, "%c", 0x1); . This statement will write a byte to the current offset in the file without converting it to a character (in this case, it will write 0x1).
up
-5
zaccraven at junk.com
18 years ago
Use this to get a UTF-8 Unicode CSV file that opens properly in Excel:

$tmp = chr(255).chr(254).mb_convert_encoding( $tmp, 'UTF-16LE', 'UTF-8');
$write = fwrite( $filepath, $tmp );

Use a tab character, not comma, to seperate the fields in the $tmp.

Credit for this goes to someone called Eugene Murai, I found this solution by him after searching for several hours.
To Top