PHP Japan Conference 2024

file_put_contents

(PHP 5, PHP 7, PHP 8)

file_put_contents将数据写入文件

描述

file_put_contents(
    字符串 $filename,
    混合类型 $data,
    整数 $flags = 0,
    ?资源 $context = null
): 整数|false

此函数等同于连续调用 fopen()fwrite()fclose() 来将数据写入文件。

如果 filename 不存在,则创建该文件。否则,将覆盖现有文件,除非设置了 FILE_APPEND 标志。

参数

filename

要写入数据的文件的路径。

data

要写入的数据。可以是 字符串数组 资源。

如果 data 资源,则该流的剩余缓冲区将被复制到指定的文件。这类似于使用 stream_copy_to_stream()

您还可以将 data 参数指定为一维数组。这等同于 file_put_contents($filename, implode('', $array))

flags

flags 的值可以是以下标志的任意组合,用二进制 OR (|) 运算符连接。

可用标志
标志 描述
FILE_USE_INCLUDE_PATH 在 include 目录中搜索 filename。有关更多信息,请参见 include_path
FILE_APPEND 如果文件 filename 已存在,则将数据追加到文件而不是覆盖它。
LOCK_EX 在继续写入时获取文件的独占锁。换句话说,在 fopen() 调用和 fwrite() 调用之间会发生 flock() 调用。这与使用模式“x”的 fopen() 调用并不相同。

context

使用 stream_context_create() 创建的有效上下文资源。

返回值

此函数返回写入文件的字节数,或者在失败时返回 false

警告

此函数可能返回布尔值 false,但也可能返回一个计算结果为 false 的非布尔值。有关更多信息,请阅读关于 布尔值 的部分。使用 === 运算符 来测试此函数的返回值。

示例

示例 #1 简单用法示例

<?php
$file
= 'people.txt';
// 打开文件以获取现有内容
$current = file_get_contents($file);
// 将新的人添加到文件中
$current .= "John Smith\n";
// 将内容写回文件
file_put_contents($file, $current);
?>

示例 #2 使用标志

<?php
$file
= 'people.txt';
// 要添加到文件的新人员
$person = "John Smith\n";
// 将内容写入文件,
// 使用 FILE_APPEND 标志将内容追加到文件的末尾
// 并使用 LOCK_EX 标志防止其他人同时写入文件
file_put_contents($file, $person, FILE_APPEND | LOCK_EX);
?>

注释

注意: 此函数是二进制安全的。

提示

如果启用了 fopen 封装器,则可以使用 URL 作为此函数的文件名。有关如何指定文件名的更多详细信息,请参见 fopen()。有关各种封装器的功能、使用方法说明以及它们可能提供的任何预定义变量的信息链接,请参阅 支持的协议和封装器

参见

添加注释

用户贡献的注释 19 个注释

TrentTompkins at gmail dot com
16 年前
如果尝试将文件放入不存在的目录中,则 File put contents 会失败。这将创建该目录。

<?php
function file_force_contents($dir, $contents){
$parts = explode('/', $dir);
$file = array_pop($parts);
$dir = '';
foreach(
$parts as $part)
if(!
is_dir($dir .= "/$part")) mkdir($dir);
file_put_contents("$dir/$file", $contents);
}
?>
[email protected]
13年前
很明显,此函数仅适用于单次写入。如果要多次写入同一文件,则应使用`fopen`、`fwrite`和`fclose`自行处理。

基准测试如下:

`file_put_contents()`进行1,000,000次写入 - 3次基准测试的平均值

实际时间 0分3.932秒
用户时间 0分2.487秒
系统时间 0分1.437秒

`fopen()` `fwrite()` 进行1,000,000次写入,`fclose()` - 3次基准测试的平均值

实际时间 0分2.265秒
用户时间 0分1.819秒
系统时间 0分0.445秒
[email protected]
5年前
该方法的简化版本: https://php.net/manual/ru/function.file-put-contents.php#84180

<?php
function file_force_contents( $fullPath, $contents, $flags = 0 ){
$parts = explode( '/', $fullPath );
array_pop( $parts );
$dir = implode( '/', $parts );

if( !
is_dir( $dir ) )
mkdir( $dir, 0777, true );

file_put_contents( $fullPath, $contents, $flags );
}

file_force_contents( ROOT.'/newpath/file.txt', 'message', LOCK_EX );
?>
[email protected]
11年前
重要的是要理解,`LOCK_EX` 不会阻止读取文件,除非你使用 PHP 的 `flock` 函数显式地获取读取锁(共享锁)。

例如,在并发场景中,如果你不这样包装 `file_get_contents`,它可能会返回空值。

<?php
$myfile
=fopen('test.txt','rt');
flock($myfile,LOCK_SH);
$read=file_get_contents('test.txt');
fclose($myfile);
?>

如果你的代码对文件执行 `file_get_contents` 操作,更改字符串,然后使用 `file_put_contents` 重新保存,你最好确保正确执行此操作,否则你的文件可能会随机被清空。
[email protected]
14年前
请注意,当使用 FTP 服务器保存时,必须传递一个额外的流上下文,告诉 PHP 覆盖文件。

<?php
/* 设置 FTP 主机名 */
$user = "test";
$pass = "myFTP";
$host = "example.com";
$file = "test.txt";
$hostname = $user . ":" . $pass . "@" . $host . "/" . $file;

/* 文件内容 */
$content = "this is just a test.";

/* 创建一个流上下文,告诉 PHP 覆盖文件 */
$options = array('ftp' => array('overwrite' => true));
$stream = stream_context_create($options);

/* 最后,写入内容 */
file_put_contents($hostname, $content, 0, $stream);
?>
匿名用户
2年前
创建子目录的简化方法版本

function path_put_contents($filePath, $contents, $flags = 0) {

if (! is_dir($dir = implode('/', explode('/', $filePath, -1))))
mkdir($dir, 0777, true);
file_put_contents($filePath, $contents, $flags);
}
匿名用户
7年前
确保在失败的情况下不会损坏任何内容。

<?php

function file_put_contents_atomically($filename, $data, $flags = 0, $context = null) {
if (
file_put_contents($filename."~", $data, $flags, $context) === strlen($contents)) {
return
rename($filename."~",$filename,$context);
}

@
unlink($filename."~", $context);
return
FALSE;
}

?>
[email protected]
18年前
回复之前的评论

如果你想在PHP4中模拟这个函数,你需要返回写入的字节数,并支持数组和标志。

我只能找出`FILE_APPEND`标志和数组支持。如果我能弄清楚“资源上下文”和其他标志,我也会包含它们。

<?

define('FILE_APPEND', 1);
function file_put_contents($n, $d, $flag = false) {
$mode = ($flag == FILE_APPEND || strtoupper($flag) == 'FILE_APPEND') ? 'a' : 'w';
$f = @fopen($n, $mode);
if ($f === false) {
return 0;
} else {
if (is_array($d)) $d = implode($d);
$bytes_written = fwrite($f, $d);
fclose($f);
return $bytes_written;
}
}

?>
[email protected]
20年前
此功能现在在 PEAR 包 PHP_Compat 中实现。

有关在不升级 PHP 版本的情况下使用此函数的更多信息,请参阅以下链接:

http://pear.php.net/package/PHP_Compat
[email protected]
7年前
我正在更新一个已发布的函数,因为它在没有目录的情况下会失败。它还会返回最终值,以便你可以确定实际文件是否已写入。

public static function file_force_contents($dir, $contents){
$parts = explode('/', $dir);
$file = array_pop($parts);
$dir = '';

foreach($parts as $part) {
if (! is_dir($dir .= "{$part}/")) mkdir($dir);
}

return file_put_contents("{$dir}{$file}", $contents);
}
[email protected]
13年前
将文件从本地主机上传到任何FTP服务器。
请注意,已使用 `ftp_chdir` 代替直接放置远程文件路径……在 `ftp_put` 中……远程文件应仅为文件名

<?php
$host
= '*****';
$usr = '*****';
$pwd = '**********';
$local_file = './orderXML/order200.xml';
$ftp_path = 'order200.xml';
$conn_id = ftp_connect($host, 21) or die ("无法连接到主机");
ftp_pasv($resource, true);
ftp_login($conn_id, $usr, $pwd) or die("无法登录");
// 执行文件上传
ftp_chdir($conn_id, '/public_html/abc/');
$upload = ftp_put($conn_id, $ftp_path, $local_file, FTP_ASCII);
if(
$upload) { $ftpsucc=1; } else { $ftpsucc=0; }
// 检查上传状态:
print (!$upload) ? '上传失败' : '上传完成';
print
"\n";
// 关闭FTP流
ftp_close($conn_id);
?>
Brandon Lockaby
13年前
在析构函数中调用 file_put_contents 将导致文件写入 SERVER_ROOT…
wjsams at gmail dot com
15年前
file_put_contents() 会去除最后一行尾部的换行符

如果使用 file_put_contents() 写入文件时,确实需要在文件末尾添加额外的换行符,则必须在行尾附加额外的 PHP_EOL,如下所示。

<?php
$a_str
= array("these","are","new","lines");
$contents = implode(PHP_EOL, $a_str);
$contents .= PHP_EOL . PHP_EOL;
file_put_contents("newfile.txt", $contents);
print(
"|$contents|");
?>

您可以看到,打印 $contents 时会得到两个额外的换行符,但如果您查看 newfile.txt 文件,则只会得到一个。
curda222 at gmail dot com
10个月前
来自 TrentTompkins at gmail dot com 的改进和改进的代码

注意:添加了错误响应
注意:添加了目录检测
注意:添加了根目录检测
注意:创建文件夹时添加了权限

function file_force_contents($dir, $contents, $flags = 0){
if (strpos($dir, "../") === 0){
$dir = str_replace("..", substr(__DIR__, 0, strrpos(__DIR__, "/")), $dir);
}
$parts = explode('/', $dir);
if(is_array($parts)){
$file = array_pop($parts);
$dir = '';
foreach($parts as $part)
if(!is_dir($dir .= "/$part")){
mkdir($dir, 0777, true);
}
if(file_put_contents("$dir/$file", $contents, $flags) === false ){
return false;
}
}else{
if(file_put_contents("$dir", $contents, $flags) === false ){
return false;
}
}
}

-Oliver Leuyim Angel
John Galt
15年前
我使用 file_put_contents() 作为非常简单的点击计数器的方法。以下是两个不同的极其简单的点击计数器示例,每个示例都只有一行代码。

请记住,它们效率并不高。您必须有一个名为 counter.txt 的文件,其初始值为 0。

对于文本点击计数器
<?php
$counter
= file_get_contents("counter.txt"); $counter++; file_put_contents("counter.txt", $counter); echo $counter;
?>

或图形点击计数器
<?php
$counter
= file_get_contents("counter.txt"); $counter++; file_put_contents("counter.txt", $counter); for($i = 0; $i < strlen($counter); $i++) echo "<img src=\"counter/".substr($counter, $i, 1).".gif\" alt=\"".substr($counter, $i, 1)."\" />";
?>
aabaev arroba gmail coma com
8年前
我建议扩展 TrentTompkins at gmail dot com 的 file_force_contents() 函数,添加对补丁是否类似于“../foo/bar/file”的验证

if (strpos($dir, "../") === 0)
$dir = str_replace("..", substr(__DIR__, 0, strrpos(__DIR__, "/")), $dir);
gurjindersingh at SPAM dot hotmail dot com
10年前
如果您尝试将文件放入不存在的目录中,则 File put contents 会失败。此函数创建目录。

我已经更新了“TrentTompkins at gmail dot com”的代码。谢谢
<?php
/**
* @param string $filename <p>文件名,包括文件夹。
* 例如 :: /path/to/file/filename.ext 或 filename.ext</p>
* @param string $data <p>要写入的数据。
* </p>
* @param int $flags 与 file_put_contents 使用的标志相同。
* 更多信息:https://php.net/manual/en/function.file-put-contents.php
* @return bool <b>TRUE</b> 文件创建成功 <br> <b>FALSE</b> 文件创建失败。
*/
function file_force_contents($filename, $data, $flags = 0){
if(!
is_dir(dirname($filename)))
mkdir(dirname($filename).'/', 0777, TRUE);
return
file_put_contents($filename, $data,$flags);
}
// 用法

file_force_contents('test1.txt','test1 content'); // 创建 test1.txt

file_force_contents('test2/test2.txt','test2 content');
// 创建 test2/test2.txt 和 "test2" 文件夹。

file_force_contents('~/test3/test3.txt','test3 content');
// 创建 /path/to/user/directory/test3/test3.txt 和用户目录中的 "test3" 文件夹 (在 Linux 上检查 "ll ~/ | grep test3")。
?>
error at example dot com
13年前
值得注意的是,使用此函数时,必须确保使用正确的路径。我正在使用它来帮助处理错误处理程序中的日志记录,有时它会工作——而其他时候则不会。最终是因为有时它从不同的路径调用,导致无法写入日志文件。

__DIR__ 是你的朋友。
vahkos at mail dot ru
12年前
如果文件名不正确(例如,末尾有错误的符号 /n,/t),file_put_contents 不会发出错误消息。
这就是为什么对文件名使用 trim() 的原因。
$name=trim($name);
file_put_contents($name,$content);
To Top