0

0

PHP如何实现文件读写?使用fopen和fwrite操作文件

蓮花仙者

蓮花仙者

发布时间:2025-09-05 15:36:02

|

358人浏览过

|

来源于php中文网

原创

PHP文件读写核心是fopen()配合fread()/fwrite()和fclose(),选择正确模式如'r'读、'w'写(清空)、'a'追加,避免数据丢失;需检查fopen()返回值确保文件打开成功,使用flock()处理并发写入,防止数据损坏;安全上禁用用户输入路径防目录遍历,用basename()过滤文件名,限制open_basedir和文件权限;大文件应分块读写避免内存溢出,可用stream_copy_to_stream()高效复制;高并发场景推荐消息队列或Monolog等日志库替代直接文件操作。

php如何实现文件读写?使用fopen和fwrite操作文件

PHP中实现文件读写,最核心也是最基础的方式就是通过

fopen()
函数打开文件,并根据需求选择不同的操作模式(比如读取、写入或追加),接着使用
fread()
fwrite()
进行实际的数据交换,最后务必用
fclose()
关闭文件句柄,这不仅是释放资源,更是保证数据完整性的关键一步。

解决方案

在PHP里,文件操作常常围绕着几个核心函数展开,

fopen()
fwrite()
fread()
fclose()
是其中的基石。这套组合拳几乎能应对所有基本的文件读写需求。

首先,

fopen($filename, $mode)
是打开文件的关键。
$filename
自然是你要操作的文件路径,而
$mode
则决定了你打算对文件做什么。比如说,如果你想写入内容,通常会用
'w'
(写入,会清空文件内容)或
'a'
(追加,在文件末尾添加内容)。如果只是想读取,那就用
'r'

打开文件后,如果

fopen()
返回的不是
false
(这意味着文件成功打开了),你就会得到一个文件句柄(一个资源类型变量)。有了这个句柄,你就可以用
fwrite($handle, $string)
向文件写入数据了。
$handle
就是你刚刚得到的句柄,
$string
则是你想要写入的内容。
fwrite()
会返回写入的字节数,这在某些需要精确控制的场景下很有用。

立即学习PHP免费学习笔记(深入)”;

要读取文件,则使用

fread($handle, $length)
$handle
同样是文件句柄,而
$length
则指定了你要从文件中读取多少字节。如果你想读取整个文件,可以先用
filesize($filename)
获取文件大小,然后把这个大小作为
$length
传给
fread()

无论你做了什么操作,最后一步,也是非常重要的一步,就是调用

fclose($handle)
来关闭文件。这就像你用完一个工具后把它放回原位,防止资源泄露,也避免了文件被其他进程锁住或损坏的风险。

这里有一个简单的例子,演示如何先写入后读取一个文件:

";
} else {
    // 成功打开,开始写入
    $bytesWritten1 = fwrite($fileHandle, $dataToWrite);
    $bytesWritten2 = fwrite($fileHandle, $moreData);

    if ($bytesWritten1 === false || $bytesWritten2 === false) {
        echo "写入文件 '$filePath' 时发生错误。
"; } else { echo "成功写入 $bytesWritten1 字节和 $bytesWritten2 字节到 '$filePath'。
"; } fclose($fileHandle); // 写入完成后记得关闭 } // 尝试读取文件内容 // 'r' 模式表示只读 $fileHandle = fopen($filePath, 'r'); if ($fileHandle === false) { echo "抱歉,无法打开文件 '$filePath' 进行读取。
"; } else { // 读取整个文件内容,这里用 filesize() 获取文件大小 $fileContent = fread($fileHandle, filesize($filePath)); if ($fileContent === false) { echo "读取文件 '$filePath' 时发生错误。
"; } else { echo "文件 '$filePath' 的内容如下:
"; echo "
" . htmlspecialchars($fileContent) . "
"; // 用 pre 和 htmlspecialchars 保持格式和避免XSS } fclose($fileHandle); // 读取完成后也要关闭 } ?>

这个例子展示了最基本的流程,但实际应用中,错误处理和权限管理是同样重要的。

PHP文件操作中,
fopen
的各种模式(
r
,
w
,
a
等)究竟有何区别?

我个人觉得,理解

fopen
的这些模式是PHP文件操作的基石,选错了模式,轻则数据丢失,重则程序崩溃,甚至可能埋下安全隐患。每种模式都有其特定的行为和适用场景,掌握它们能让你在处理文件时游刃有余。

  • 'r'
    (只读模式)
    :这是最安全的模式,文件指针会定位在文件开头。如果你试图写入,会报错。如果文件不存在,
    fopen()
    会返回
    false
  • 'w'
    (只写模式)
    :这个模式有点“粗暴”。它会尝试打开文件进行写入,如果文件不存在,会尝试创建它。但如果文件已经存在,它的内容会被完全清空,然后文件指针定位在开头。所以,用
    'w'
    时要格外小心,别不小心把重要数据给覆盖了。
  • 'a'
    (追加模式)
    :这是我个人在日志记录等场景下最常用的模式。它也是打开文件进行写入,如果文件不存在,会创建它。但如果文件存在,文件指针会定位在文件末尾,所有新写入的内容都会追加到现有内容的后面,不会覆盖旧数据。
  • 'x'
    (独占写入模式)
    :这个模式比较特殊,它尝试创建一个新文件并以只写方式打开。如果文件已经存在,
    fopen()
    会返回
    false
    ,并且会生成一个错误。这对于确保你创建的文件是全新的,避免覆盖现有文件非常有用。
  • 'r+'
    (读写模式)
    :文件指针在开头,允许你同时读取和写入。如果文件不存在,
    fopen()
    会返回
    false
  • 'w+'
    (读写模式,清空)
    :与
    'w'
    类似,它会清空文件内容(如果文件存在),然后允许读写。文件指针在开头。
  • 'a+'
    (读写模式,追加)
    :与
    'a'
    类似,文件指针在末尾,允许读写。读取时会从文件开头开始,但写入时总是在文件末尾追加。

此外,你还可以在这些模式后面加上

'b'
,比如
'rb'
'wb'
,这表示以二进制模式打开文件。虽然在Linux/Unix系统上通常没什么区别,但在Windows系统上,二进制模式可以避免一些换行符转换的问题,尤其是在处理图片、视频等非文本文件时,加上
'b'
是个好习惯。

B2S商城系统
B2S商城系统

B2S商城系统B2S商城系统是由佳弗网络工作室凭借专业的技术、丰富的电子商务经验在第一时刻为最流行的分享式购物(或体验式购物)推出的开源程序。开发采用PHP+MYSQL数据库,独立编译模板、代码简洁、自由修改、安全高效、数据缓存等技术的应用,使其能在大浏览量的环境下快速稳定运行,切实节约网站成本,提升形象。注意:如果安装后页面打开出现找不到数据库等错误,请删除admin下的runtime文件夹和a

下载

除了基本的读写,PHP文件操作中常见的错误处理和安全实践有哪些?

很多时候,我们写代码只想着功能实现,却忽略了这些“脏活累活”。但说真的,一个没有健壮错误处理和安全考量的文件操作,迟早会出问题,甚至可能导致严重的安全漏洞。

错误处理:

  1. 检查
    fopen()
    的返回值
    :这是最直接的错误检查。如果
    fopen()
    返回
    false
    ,说明文件打开失败了。这时候,你可以使用
    error_get_last()
    来获取更详细的错误信息,比如“Permission denied”(权限不足)或“No such file or directory”(文件或目录不存在)。
    $handle = fopen('non_existent_file.txt', 'r');
    if ($handle === false) {
        $error = error_get_last();
        echo "文件打开失败: " . $error['message'] . "
    "; }
  2. flock()
    文件锁
    :在高并发环境下,多个进程或请求同时尝试写入同一个文件可能会导致数据损坏或不一致。
    flock()
    函数可以为文件提供一个咨询性锁(advisory lock)。
    $handle = fopen('shared_log.txt', 'a');
    if ($handle && flock($handle, LOCK_EX)) { // 独占写入锁
        fwrite($handle, "并发写入测试:" . date('H:i:s') . "\n");
        fflush($handle); // 确保数据写入磁盘
        flock($handle, LOCK_UN); // 释放锁
    } else {
        echo "无法获取文件锁或打开文件。
    "; } fclose($handle);

    需要注意的是,

    flock()
    是咨询性锁,意味着它依赖于所有访问该文件的程序都自觉地使用
    flock()
    。如果有的程序不使用锁,那它就可能绕过锁进行操作。

安全实践:

  1. 绝不信任用户输入的文件路径:这是文件操作安全的第一原则。如果允许用户直接指定文件路径,攻击者可能会利用“目录遍历”(Directory Traversal)漏洞来访问或修改服务器上的任意文件,例如
    ../../../../etc/passwd
    • 白名单机制:只允许用户从预定义的、安全的文件列表中选择文件。
    • basename()
      :如果你需要从用户输入中获取文件名,使用
      basename()
      函数来剥离路径信息,只留下文件名。
    • 限制目录:将用户上传或生成的文件严格限制在特定的、非Web可访问的目录中。
  2. 设置正确的文件和目录权限:使用
    chmod()
    或在服务器层面设置适当的权限。例如,Web服务器进程通常只需要对特定目录有写入权限,而对其他文件和目录则只需读取权限。避免给文件或目录设置
    777
    权限,这几乎是邀请攻击者来搞破坏。
  3. 验证和净化写入内容:如果文件内容来自用户输入,务必进行严格的验证和净化。例如,如果写入的是HTML内容,需要进行HTML实体编码或使用专业的HTML净化库,以防跨站脚本(XSS)攻击。
  4. open_basedir
    限制
    :在
    php.ini
    中配置
    open_basedir
    指令,可以限制PHP脚本能够访问的文件系统路径。这是一个非常有效的安全措施,可以防止PHP脚本访问其被授权目录之外的文件。
  5. 及时关闭文件句柄:虽然这更多是资源管理,但也间接关乎安全。未关闭的文件句柄可能导致文件被锁定,或者在某些操作系统上,文件在句柄关闭前可能无法被其他进程访问或删除。

在处理大型文件或高并发场景下,PHP的文件读写性能优化和替代方案有哪些?

当我第一次遇到要处理几GB的日志文件时,直接

file_get_contents()
差点让服务器内存爆掉。那次经历让我深刻认识到,文件操作不是简单地打开、读写、关闭,而是要根据场景灵活选择策略。

性能优化:

  1. 分块读写(Chunked Reading/Writing):对于大型文件,一次性读取或写入整个文件到内存中是非常危险的,可能导致内存溢出。应该采用分块的方式,每次只读取或写入一小部分数据。
    • fread($handle, $bufferSize)
      :循环读取,每次读取一个固定大小的缓冲区。
    • fwrite($handle, $dataChunk)
      :循环写入,每次写入一个数据块。
      // 示例:分块读取大文件
      $handle = fopen('large_file.log', 'r');
      if ($handle) {
      $bufferSize = 4096; // 4KB缓冲区
      while (!feof($handle)) {
          $chunk = fread($handle, $bufferSize);
          // 处理 $chunk 数据,例如写入数据库或另一个文件
          // echo $chunk;
      }
      fclose($handle);
      }
  2. stream_copy_to_stream()
    :如果你只是想将一个流(例如文件)的内容复制到另一个流,
    stream_copy_to_stream()
    是一个非常高效的选择,它不会将整个内容加载到PHP内存中。
    $source = fopen('source.txt', 'r');
    $dest = fopen('destination.txt', 'w');
    if ($source && $dest) {
        stream_copy_to_stream($source, $dest);
        fclose($source);
        fclose($dest);
        echo "文件复制完成。
    "; }
  3. file_get_contents()
    /
    file_put_contents()
    的局限性
    :对于小型文件,这两个函数非常方便且性能不错,因为它们内部做了很多优化。但对于大型文件,它们会将整个文件内容加载到内存中,这正是需要避免的。

替代方案:

当文件操作成为性能瓶颈,或者数据结构化程度较高、需要复杂查询时,就应该考虑更专业的解决方案了。

  1. 数据库(Database):对于结构化数据,无论是关系型数据库(MySQL, PostgreSQL)还是NoSQL数据库(MongoDB, Redis),都比平面文件有巨大优势。它们提供了强大的查询语言、索引、事务支持、并发控制和数据持久性。日志文件如果需要频繁查询和分析,存入数据库是更好的选择。
  2. 消息队列(Message Queues):在高并发写入场景(例如大量日志),直接写入文件可能会导致I/O瓶颈。消息队列(如RabbitMQ, Kafka)可以作为缓冲层,将写入请求异步化。应用程序将日志消息发送到队列,然后由独立的消费者进程从队列中取出消息并写入文件或数据库。这可以显著提高前端响应速度和系统吞吐量。
  3. 专门的日志服务或库
    • PHP Monolog:这是一个非常流行的PHP日志库,它支持多种日志处理器(handlers),可以将日志写入文件、数据库、远程服务等,并支持日志级别、格式化等高级功能。
    • 外部日志管理系统:对于企业级应用,可以考虑使用ELK Stack(Elasticsearch, Logstash, Kibana)、Splunk等专业的日志管理和分析平台。它们能够收集、存储、索引和可视化海量的日志数据,提供强大的搜索和分析能力。

选择哪种方案,最终还是要看你的具体需求:数据的结构化程度、读写频率、并发量、数据量大小以及对数据一致性和持久性的要求。没有银弹,只有最适合的工具。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

668

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

247

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

281

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

515

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

256

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

386

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

533

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

602

2023.08.14

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.3万人学习

Node.js 教程
Node.js 教程

共57课时 | 9.6万人学习

CSS3 教程
CSS3 教程

共18课时 | 5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号