fwrite

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

fwrite二进制安全文件写入

描述

fwrite(资源 $stream, 字符串 $data, ?整数 $length = null): 整数|false

fwrite()data 的内容写入指向由 stream 指向的文件流。

参数

stream

文件系统指针 资源,通常使用 fopen() 创建。

data

要写入的字符串。

length

如果 length 是一个 整数,写入将在写入 length 个字节或到达 data 的末尾后停止,以先发生者为准。

返回值

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

错误/异常

fwrite() 在失败时引发 E_WARNING

变更日志

版本 描述
8.0.0 length 现在可以为空。

示例

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

<?php
$filename
= 'test.txt';
$somecontent = "将此添加到文件\n";

// 让我们先确保文件存在并且是可写的。
if (is_writable($filename)) {

// 在我们的示例中,我们以追加模式打开 $filename。
// 文件指针位于文件末尾,因此
// 当我们 fwrite() 它时,$somecontent 将放在那里。
if (!$fp = fopen($filename, 'a')) {
echo
"无法打开文件 ($filename)";
exit;
}

// 将 $somecontent 写入我们打开的文件。
if (fwrite($fp, $somecontent) === FALSE) {
echo
"无法写入文件 ($filename)";
exit;
}

echo
"成功,将 ($somecontent) 写入文件 ($filename)";

fclose($fp);

} else {
echo
"文件 $filename 不可写";
}
?>

注释

注意:

写入网络流可能会在整个字符串写入之前结束。可以检查 fwrite() 的返回值

<?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() 模式参数中包含 'b' 的方式打开。

注意:

如果 stream 在追加模式下 fopen()ed,fwrite() 是原子的(除非 data 的大小超过文件系统的块大小,在某些平台上,并且只要文件位于本地文件系统上)。也就是说,在调用 fwrite() 之前不需要 flock() 资源;所有数据都将在不中断的情况下写入。

注意:

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

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

// 'data.txt' 的内容现在是 123 而不是 23!
?>

参见

添加注释

用户贡献注释 33 个注释

107
nate at frickenate dot com
14 年前
在遇到 fwrite() 在完全预期返回值为 false 的情况下返回 0 的问题后,我查看了 php 的 fwrite() 本身的源代码。该函数只有在你传入无效参数时才会返回 false。任何其他错误,例如断开的管道或关闭的连接,都会导致返回值小于 strlen($string),在大多数情况下为 0。

因此,使用对 fwrite() 的重复调用循环,直到写入的字节数总和等于完整值的 strlen() 或在错误时预期 false,如果连接丢失,会导致无限循环。

这意味着来自文档的 fwrite_stream() 示例代码,以及评论中其他人发布的所有“帮助器”函数,都已损坏。你*必须*检查返回值是否为 0,并在立即中止或跟踪最大重试次数。

以下是来自文档的示例。此代码很糟糕,因为断开的管道会导致 fwrite() 无限循环,返回值为 0。由于循环只有在 fwrite() 返回 false 或成功写入所有字节时才中断,因此在失败时会发生无限循环。

<?php
// BROKEN 函数 - fwrite() 返回 0 时出现无限循环
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;
}
?>
3
divinity76 at gmail dot com
3 年前
如果您需要一个写入所有数据的函数,可以尝试一下

<?php

/**
* 写入所有数据或抛出异常
*
* @param mixed $handle
* @param string $data
* @throws \RuntimeException 当 fwrite 返回 <1 但仍有更多数据要写入时
* @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("只能写入 {$written_total}/{$original_len} 字节!" );
}
$written_total += $written_now;
$data = substr($data, $written_now);
$len -= $written_now;
// assert($len > 0);
// assert($len === strlen($data));
}
}
}
3
niklesh at example dot com
4 年前
$handles 也可以用于在控制台中输出,如下面的例子所示

fwrite(STDOUT, "控制台输出");
5
Anonymous
8 年前
// 你想复制虚拟文件或发送虚拟文件
// 即使发送超过 4GB 的文件并写入,也不需要使用 FSEEK,它受 PHP_INT_MAX 的限制,可以在 32 位或 64 位系统上运行
// fwrite 和 fread 没有指针位置限制

<?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;
}
?>
4
Chris Blown
21 年前
不要忘记检查 fwrite 是否返回错误!即使你成功地打开了文件进行写入,也不一定就能写入。

在某些系统上,如果文件系统已满,你仍然可以打开文件并创建文件系统 inode,但 fwrite 会失败,导致生成一个零字节文件。
2
synnus at gmail dot com
8 年前
// 你想复制虚拟文件或发送虚拟文件
// 即使发送超过 4GB 的文件并写入,也不需要使用 FSEEK,它受 PHP_INT_MAX 的限制,可以在 32 位或 64 位系统上运行
// fwrite 和 fread 没有指针位置限制

<?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;
}
?>
5
dharris dot nospam at removethispart dot drh dot net
16 年前
有些人说,当写入套接字时,可能不会写入所有请求写入的字节。你可能需要再次调用 fwrite 来写入第一次没有写入的字节。(至少在 UNIX 中,write() 系统调用就是这样工作的。)

这是一个有用的代码(警告:未经多字节字符集测试)

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;
}

像这样调用它

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

if ( ! $rv )
die("无法将 request_string 写入套接字");
if ( $rv != strlen($request_string) )
die("在写入 request_string 时,套接字写入排序");
3
Anonymous
15 年前
如果您使用指针在文件中间写入,它会覆盖现有的内容,而不是将文件其余部分移开。
2
chedong at hotmail dot com
21 年前
如果 fwrite 输出没有给出长度参数,则会去掉斜杠,例如

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

out.txt 将是
c:^@1.txt
没有转义的 '\\0' 将是 '\0' ==> 0x00。

正确的做法是将 fwrite 更改为
fwrite($out, $str, strlen($str));
3
php at biggerthanthebeatles dot com
20 年前
希望这对其他新手有所帮助。

如果您正在将数据写入 Windows 系统上的 txt 文件,并且需要换行符,请使用 \r\n。这将写入十六进制 OD OA。

例如
$batch_data= "一些数据... \r\n";
fwrite($fbatch,$batch_data);

这相当于在记事本中打开一个 txt 文件,在行尾按回车键并保存它。
0
synnus at gmail dot com
3 年前
<?php
/*
写入带正偏移量的偏移量

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

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

$handel = fopen( myfilname );
$t_f_max 是以 BYTE 为单位的最大文件大小,例如:19998
$offset 是偏移量 BYTE 中的位置,例如:19995
$bin 您要写入的二进制数据

在 32 位和 64 位中工作
*/

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;
}

?>
0
2184364 at gmail dot com
4 年前
//fwrite 覆盖写入,例如,此示例(win)可能具有误导性

$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);

//添加 ftruncate ($ fp, 0);
//这将覆盖文件

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);
-1
Jon Haynes
13 年前
小心在 fwrite 操作中使用保留的 Windows 文件名。

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

上面的脚本将在它能够回显“done”之前挂起(在 Windows 7 上测试)。

这是由于我们最喜欢的操作系统的另一个“特性”,其中文件名如 prn.xxx、con.xxx、com1.xxx 和 aux.xxx(其中 xxx 是任何文件名扩展名)是 Windows 保留的设备名称。尝试创建/读取/写入这些文件会使解释器挂起。
-1
qrworld.net
9 年前
这里有一个在网站 http://softontherocks.blogspot.com/2014/11/funcion-para-escribir-en-un-fichero-log.html 上找到的函数,其中包含如何创建日志文件的示例。

该函数是

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'); // 打开或创建文件以写入并追加信息
fputs($fp, "$msg\n"); // 将数据写入打开的文件
fclose($fp); // 关闭文件
}
-2
chill at cuna dot org
19 年前
在 PHP 4.3.7 中,fwrite 在失败时返回 0 而不是 false。
以下示例将为现有文件 test.txt 输出“SUCCESS: 0 字节已写入”。

$fp = fopen("test.txt", "rw");
if (($bytes_written = fwrite($fp, "This is a test")) === false) {
echo "无法写入 test.txt\n\n";
} else {
echo "SUCCESS: $bytes_written 字节已写入\n\n";
}
-4
dominic at varspool dot com
10 年前
请注意,可选的 $length 参数应为 int,并且不能通过传递 null 来跳过。

也就是说,`fwrite($handle, $string, null)` 被视为 `fwrite($handle, $string, 0)`,并且将写入零字节,而不是整个字符串。
-3
james at nicolson dot biz
19 年前
我无法完全理解 MKP Dev 点击次数计数器的工作原理……这是我修改后的方法
<?
function hitcount()
{
$file = "counter.txt";
if ( !file_exists($file)){
touch ($file);
$handle = fopen ($file, 'r+'); // 让我们打开以供读写
$count = 0;

}
else{
$handle = fopen ($file, 'r+'); // 让我们打开以供读写
$count = fread ($handle, filesize ($file));
settype ($count,"integer");
}
rewind ($handle); // 返回到开头
/*
* 请注意,我们不会遇到 9 个字符少于
* 10 个字符的问题,因为我们一直在递增,所以我们始终会至少写入
* 与我们读取的字符一样多的字符
**/
fwrite ($handle, ++$count); // 不要忘记递增计数器
fclose ($handle); // 完成

return $count;
}
?>
-5
Jake Roberts
21 年前
使用时请谨慎

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

这将在您读取的文件长度为零时导致错误。

改用

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

因此,它在读取零字节时将成功,但会检测到错误并返回 FALSE。
-5
bluevd at gmail dot com
19 年前
注意编写简单的点击次数计数器代码时的错误
<?php
$cont
=fopen('cont.txt','r');
$incr=fgets($cont);
//echo $incr;
$incr++;
fclose($cont);
$cont=fopen('cont.txt','a');
fwrite($cont,$incr);
fclose($cont);
?>

为什么?注意第二个 fopen -> $cont=fopen('cont.txt','a');
它以写入模式(a)打开文件。当它添加递增的
值($incr)时,它会将其添加到旧值的旁边……因此,大约 5 次打开计数器
页面将使您的点击次数看起来像这样
012131214121312151.21312141213E+ .... 你明白了。
令人讨厌,不是吗?记住以“w”模式(将文件截断
为 0)打开文件。这样做将清除文件内容,并确保
您的计数器正常工作。这是最终代码

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

请注意,这工作正常 =)
XU(别名 Iscu Andrei)
-4
ceo at l-i-e dot com
15 年前
如果您尝试将二进制/结构化数据(例如,用于 (int) 的 4 字节序列)写入文件,则需要使用
https://php.net/pack
-7
james at facepwn dot com
15 年前
if (is_writable($filename)) {

也可以是

if (is_writable($filename) or die ("无法写入 ".$filename)) {
-7
Anonymous
9 年前
糟糕的示例!

fwrite 的结果可能是 FALSE 或 0。

所以它应该正确地

if (false === fwrite($handle, $somecontent)) { ....
-6
chad 0x40 herballure 0x2e com
16 年前
请记住检查 fwrite() 的返回值。特别是,写入套接字可能会返回少于请求的字节,您必须使用剩余的数据再次尝试。
-4
David Spector
8 年前
这可能会节省您的时间:请注意,“二进制安全文件写入”或在 fopen 中使用 b 模式并不意味着 fwrite 可以写入二进制文件。它只能写入字符串(或单个字符)。例如,尝试使用 fwrite 写入字节 0x1 会导致写入字节值 0x31。

如果您希望写入二进制值(位、字节、整数等),请使用类似 fprintf($Res, "%c", 0x1); 的语句。此语句将在文件中的当前偏移量处写入一个字节,而不会将其转换为字符(在本例中,它将写入 0x1)。
-7
sheyh
19 年前
如果您想快速创建而不使用 fopen,请使用 system、exec

system('echo "blahblah" > /path/file');
-8
oktavianus dot programmer at gmail dot com
15 年前
这是使用 fwrite 创建文件夹和创建 txt 文件的另一个示例。

<?php
$mypath
="testdir\\subdir\\test";
mkdir($mypath,0777,TRUE);
$filename = $mypath.'\test.txt';
$handle = fopen($filename,"x+");
$somecontent = "Add this to the file Oktavianus";
fwrite($handle,$somecontent);
echo
"Success";
fclose($handle);
?>

请尝试...
Oktavianus
-5
zaccraven at junk.com
17 年前
使用此方法获取可以在 Excel 中正确打开的 UTF-8 Unicode CSV 文件

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

使用制表符(而不是逗号)来分隔 $tmp 中的字段。

这要归功于一位名叫 Eugene Murai 的人,我在搜索了几个小时后找到了他的解决方案。
-6
MKP Dev
19 年前
bluevd at gmail dot com 提到了一个点击计数器。在他的实现中,文件首先被打开、读取、关闭,然后再次打开+截断,然后写入,最后再次关闭。另一种方法是
<?php
$file
= 'counter.txt or whatever';
$handle = fopen ($file, 'r+'); // 以读写模式打开
$count = int (fread ($handle, filesize ($file)));
// 我们不希望将其视为字符串并尝试附加
echo "Number of hits $count";
rewind ($handle); // 返回开头
/*
* 注意,我们不会因为 9 个字符少于 10 个字符而出现问题
* 因为我们一直在递增,所以我们写入的字符数量将始终不少于读取的字符数量
**/
fwrite ($handle, ++$count); // 不要忘记递增计数器
fclose ($handle); // 完成
?>
-6
Will at EnigmaChannel dot com
19 年前
使用 fwrite 将内容写入 include 文件夹中的文件...

PHP 只有在您重新启动服务器后才会识别文件的权限设置...此脚本正常运行。(不过,仍然需要先创建空白文本文件...它不会自动创建)在 OS X Server 上..
使用 fopen 中的 1 指示 PHP 在您的 include 文件夹中查找文件。通过更改 php.ini 中的 include_path 可以更改您的 include 文件夹。
在 OS X Server 上,php.ini 位于 private/etc/php.ini.default 中。
复制该文件并将其命名为 php.ini。

默认 include 路径是 usr/lib/php。
(所有这些文件夹都是隐藏的 - 使用 TinkerTool 来显示它们)

<?php
$file
= fopen('textfile.txt', 'a', 1);
$text="\n Your text to write \n ".date('d')."-".date('m')."-".date('Y')."\n\n";
fwrite($file, $text);
fclose($file);
?>
-8
kzevian at cybercable dot net dot mx
19 年前
我需要追加内容,但我需要在文件的开头写入内容,经过几个小时的努力,我找到了这个方法

$file = "file.txt";
if (!file_exists("file.txt")) touch("file.txt");
$fh = fopen("file.txt", "r");
$fcontent = fread($fh, filesize("file.txt"));

$towrite = "$newcontent $fcontent";

$fh22 = fopen('file.txt', 'w+');
fwrite($fh2, $towrite);
fclose($fh);
fclose($fh2);
-10
Andi
21 年前
[编辑说明
当 auto_detect_line_endings 运行时配置设置设置为 On 时,应该可以解决此问题。]

我发现当使用 \r 作为换行符写入文件时,file() 无法从该文件中读取数据。
使用 \n 解决问题。
-12
elinor_hust at REMOVETHIS dot hotmail dot com
16 年前
请记住,在输出特殊字符(如 \n)时,请使用双引号,否则它们将按字面意思输出。

...
-20
cutmaster at fearlesss dot com
17 年前
对于像我一样花了很长时间(几小时)才弄明白为什么 fwrite 无法创建真正的 utf-8 文件的人来说,这里是我找到的解释

我尝试执行以下操作
<?php
$myString
= utf8_encode("Test with accents éèàç");
$fh=fopen('test.xml',"w");
fwrite($fh,$myString);
fclose($fh);
?>

由于某种神秘的原因,结果文件显示了没有进行 utf-8 转换的重音符号。

我尝试了二进制模式、文本模式等等。最后我找到了它
似乎 fwrite 需要将 utf8_encode 函数放在其参数内部,才能理解它必须创建一个非文本文件
<?php
$myString
= "Test with accents éèàç";
$fh=fopen('test.xml',"w");
fwrite($fh,utf8_encode($myString));
fclose($fh);
?>
希望这能有所帮助
To Top