PHP 文件写入和读取操作实例详解【必看篇】


Posted in PHP onNovember 04, 2019

本文实例讲述了PHP 文件写入和读取操作。分享给大家供大家参考,具体如下:

文章提纲:

一.实现文件读取和写入的基本思路

二.使用fopen方法打开文件

三.文件读取和文件写入操作

四.使用fclose方法关闭文件

五.文件指针的移动

六.Windows和UNIX下的回车和换行

一.实现文件读取和写入的基本思路:

1.通过fopen方法打开文件:$fp =fopen(/*参数,参数*/),fp为Resource类型
2.进行文件读取或者文件写入操作(这里使用的函数以1中返回的$fp作为参数)
3. 调用fclose($fp)关闭关闭文件

二:使用fopen方法打开文件

fopen(文件路径[string],打开模式[string])

<1>fopen的第一个参数为文件路径
写文件路径的方式:1绝对路径,2相对路径

1绝对路径:

在windows下工作的小伙伴们应该很熟悉,windows下的路径分隔符是“\”而不是“/”,但我们在写入路径时不能以钦定的“\”为分隔符

PHP 文件写入和读取操作实例详解【必看篇】

那如果我们以“\”分隔符写入路径会怎样呢?

<?php
  $fp = fopen("C:\wamp64\www\text.txt",'w');
?>

运行后报错,提示路径参数无效

PHP 文件写入和读取操作实例详解【必看篇】

所以我们要把分隔符“\”换成“/”:

<?php
 $fp = fopen("C:/wamp64/www/text.txt",'w');
?>

运行时无报错,说明参数是有效的。

【注意】fopen函数不能理解“\”分隔符,如果你想要使用“\”,那么要使用转义,如写成:"C:\\wamp64\\www\\text.txt"这种写法也是可以的,函数也能理解,不会报错。但即使这样,也不推荐使用“\”,因为在OS(mac)下只能识别“/”不能识别“\”

本小节的结论:推荐坚持使用“/”作为分隔符

2.相对路径:

上一小节介绍的是绝对路径的写法,但这样却带来了另外一个问题:服务器的目录结构可能会有较大的改变,这时原来写的绝对路径就要全部重写了,比如在我的电脑上的目标文件路径是C:/wamp64/www/text.txt,如果我把www文件夹改名为penghuwan呢?原来写入的路径参数就失效了。所以我们引入了相对路径的写法:

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'w');
?>

• $_SERVER是PHP的超级全局变量(在代码任何地方都可访问,类型是数组),通过$_SERVER['DOCUMENT_ROOT']可取到服务器的默认根目录

服务器的默认根目录可通过php.ini修改(这个可自行百度)

• $_SERVER['DOCUMENT_ROOT']在这里等同于C:/wamp64/www

本小节的结论:推荐使用相对路径

<2>fopen的第二个参数为打开模式

设置打开模式后,我们就相当于为接下来的读写操作设置了权限:

最基本的几个模式:

“r”:只能读取文件,不能写入文件(写入操作被忽略)
“w”:只能写入文件,不能读取文件(读取操作被忽略)
“a”:只追加文件,与“w”类似,区别是“w”删除原有的内容,“a”不删除原有内容,只追加内容

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'w');
 fwrite($fp,'在写模式下写入');
 fclose($fp);
?>

在设置了写操作的权限后,就能正常地写入文件了

运行后打开C:/wamp64/www/text.txt:

PHP 文件写入和读取操作实例详解【必看篇】

这次我们把权限设置为只读,并尝试写入文本:'在只读模式下写入' ?

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
 fwrite($fp,'在读模式下写入');
 fclose($fp);
?>

运行后打开C:/wamp64/www/text.txt,发现文件内容并没有改变,说明由于没有设置相应的权限,操作被忽略了 PHP 文件写入和读取操作实例详解【必看篇】

关于打开模式的网络资料,我想大家最可能找到的是这张表:(图来自W3C) PHP 文件写入和读取操作实例详解【必看篇】

很全面,但我觉得这张表对新手有些不太友好,让人看后不知多云。 r是只读,w是只写(原来有的内容全删除),a是追加(不删除原有内容),这都好理解。

但r+,w+,和a+的区别和联系讲的实在太模糊了呀。 这里我就想详细地讲一下r+,w+,和a+三者的区别和联系:

首先r+,w+,和a+都是可读可写的,读取时的方式是一样的,关键在于写入方式的不同:

r+: 从文件[头部][覆盖]原有内容 ([不删除]原有内容);

a+:从文件[尾部][追加]内容 ([不删除]原有内容);

w+:[完全删除]原有内容,然后[再添加]新的内容

下面我依次演示上述的结论,首先我们没有写入的时候文本是”I am initialized value”(意为我是初始值)

PHP 文件写入和读取操作实例详解【必看篇】

• 采用r+模式写入文本“r+ mode”

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'r+');
 fwrite($fp,'r+ mode');
 fclose($fp);
?>

运行后再打开文本,发现“I am in”被“r+ mode”覆盖了:

PHP 文件写入和读取操作实例详解【必看篇】

• 采用a+模式写入文本“a+ mode”

基于”I am initialized value”的初始文本我们运行以下代码:  

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'a+');
 fwrite($fp,'a+ mode');
 fclose($fp);
?>

PHP 文件写入和读取操作实例详解【必看篇】

I am initialized value没有被删除和覆盖,而是在后面追加了a+ mode的这一段新文本运行多次后:

PHP 文件写入和读取操作实例详解【必看篇】

•采用w+模式写入文本“w+ mode”

基于”I am initialized value”的初始文本我们运行以下代码:

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'w+');
 fwrite($fp,'w+ mode');
 fclose($fp);
?>

运行后,我们发现”I am initialized value”已经被删除了,然后才加上了“w+ mode”这段新文本 PHP 文件写入和读取操作实例详解【必看篇】

【注意】r+,a+,w+还有一个区别是a+,w+在文件不存在时则创建文件,r+文件不存在时报错

【吐槽】:关于r+和w+,a+的区别,我找了网络上,包括W3C和各种博客文章以及那本“PHP圣经”上的各种资料,发现都是一笔带过去的,这也是我写这篇文章的原因

三.文件读取和文件写入操作

先说说几个比较重要的函数:

 file_exists():判断文件是否存在,返回布尔值

 filesize():判断一个文件大小,返回文件的字节数,为整型数字

 unlink():删除一个文件

写入文件

fwrite(资源文件对象[string],写入方式[string]),资源文件对象即为fopen方法返回的参数,为Resource类型,写入方式可以是w(或者w+,a+,r+) 已经有上面的例子,这里就不放demo了

读取文件

这是我们要读取的文件内容:

PHP 文件写入和读取操作实例详解【必看篇】

读取文件的方式有以下几种:

1.一次读取一个字节的数据 fgetc()

2.一次读取指定的字节数的数据 fread()

3.一次读取一行数据 fgets()/fgetcsv()

4.一次读完全部数据 fpassthru()/ file()

1. 一次读取一个字节 —— 通过fgetc()获取单个字节

<?php
  $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
  $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');//打开文件
  if(file_exists("$DOCUMENT_ROOT/text.txt")){//当文件存在时,才读取内容
   while(!feof($fp)){//判断文件指针是否到达末尾
    $c = fgetc($fp);//每执行一次fgetc(),文件指针就向后移动一位
    echo $c;//输出获取到的字节
   }
  }
  fclose($fp);//关闭文件
?>

运行:

PHP 文件写入和读取操作实例详解【必看篇】 

【注意】:无论是按文本格式输入输出

还是按二进制格式输出,fgetc()每次获取的是一个字节而不是一个字符!上面的例子中我们是逐个输出,现在让我们只做一次输出,看看结果怎样:

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
 echo fgetc($fp);//只做一次输出
 close($fp);
?>

运行结果如下,我们得到的不是汉字“我”,而是一个乱码,其实这个乱码就是一个字节

PHP 文件写入和读取操作实例详解【必看篇】

<?php
  $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
  $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
  echo fgetc($fp);//连续做三次输出
  echo fgetc($fp);
  echo fgetc($fp);
  fclose($fp);
?>

2.一次读取多个字节 ——通过fread()方法:

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
 echo fread($fp, 3);//一次输出三个字节即一个汉字字符(UTF-8)
 fclose($fp);
?>

运行结果:

PHP 文件写入和读取操作实例详解【必看篇】

改成:

echo fread($fp, 6);

运行结果如下,输出了6个字节也即两个汉字字符(UTF-8)

PHP 文件写入和读取操作实例详解【必看篇】

3.一次读取一行——通过fgets()获取一行内容

<?php
  $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT']
  $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');//打开文件
  if(file_exists("$DOCUMENT_ROOT/text.txt")){//当文件存在时,才读取内容
   while(!feof($fp)){//判断文件指针是否到达末尾
    $line = fgets($fp);//返回一行文本,并将文件指针移动到下一行头部
    echo $line."<br/>";//输出获取到的一行文本
   }
  }
  fclose($fp);//关闭文件
?>

PHP 文件写入和读取操作实例详解【必看篇】

fgets()其实还有第二个参数,这个参数规定了每一行能读取的最大字节数(注意是字节数不是字符数):

【注意】在UTF-8编码下汉字3字节,字母1字节下面我修改上面的一行,代码,使获取的每一行最大字符数为3(也即字节数为9)

$line = fgets($fp,10);

Demo:

PHP 文件写入和读取操作实例详解【必看篇】

【注意】:这里我fgets()里第二个参数为10,为什么是10呢?因为

1.这里的长度是按字节数算的

2.一个汉字占3个字节。fgets($fp,10)代表一次最多读取10 - 1 = 9字节

4.一次读完全部文件 ——fpassthru() or file()? fpassthru()将读取文件并直接输出(无处理过程)

<?php
  $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
  $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
  fpassthru($fp);
  fclose($fp);
?>

运行结果:

PHP 文件写入和读取操作实例详解【必看篇】

【注意】这里需要注意一点的是,我们并没有从fpassthru($fp)获取到返回值然后echo到页面上去,也就是说这个方法是会强制输出获取的内容的,而并不是像之前例子的方法那样返回文本,允许我们保存到变量中才将其输出

将读取到的全部内容保存到一个数组中,每个数组元素为一行的内容——fille()

<?php
 $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
 $file_array = file("$DOCUMENT_ROOT/text.txt");//取到文件数组
 foreach ($file_array as $value) {//输出数组元素
  echo $value."<br/>";
 }
?>

PHP 文件写入和读取操作实例详解【必看篇】

【注意】:这里我们并不需要写fopen和fclose哦!也就是说file()方法已经帮我们做了这一步了

四.使用fclose方法关闭文件

fclose()将返回一个布尔值,成功关闭为true,关闭失败为false(失败的情况很少出现,可不考虑) 是否打开文件后一定要关闭?

1即使不手写fclose,在PHP脚本执行结束后,也会自动关闭文件的

2但在一个长时间执行的脚本中,如果不写关闭文件的fclose(),在文件加锁的情况下会造成操作的阻塞,所以,写fclose是个好习惯

五.文件指针的移动

我们上面调用的读取文件的函数,其实都是基于文件指针去打印的,每读取一段字节内容,文件指针就向后移动一段字节长度,直到被读取的文件最大字节长度为止

<?php
   $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
   function print_file_pointer($fp){//定义一个打印文件指针位置的函数
    echo " <br/>//此时文件指针的位置:";
    echo ftell($fp)."<br/>";
   }
   $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
   echo fgetc($fp);//通过fgetc连续输出三个字节
   echo fgetc($fp);
   echo fgetc($fp);
   print_file_pointer($fp);//打印此刻文件指针的位置
   
   echo fread($fp,6);//通过fread一次输出6字节
   print_file_pointer($fp);//打印此刻文件指针的位置
   
   echo fgets($fp); //通过fgets输出一整行
   print_file_pointer($fp);//打印此刻文件指针的位置
   
   fpassthru($fp); //一次性输出全部内容
   print_file_pointer($fp);//打印此刻文件指针的位置
   
   fseek($fp, 33);//使文件指针移动到33字节位置
   print_file_pointer($fp);//打印此刻文件指针的位置
   
   rewind($fp);//使文件指针移动到0字节位置(初始位置)
   print_file_pointer($fp);//打印此刻文件指针的位置
$fclose($fp);
?>

Demo:

PHP 文件写入和读取操作实例详解【必看篇】

所以我们需要正确理解fgets(),fpassthru()这些函数的作用:

fgets():从当前文件指针的位置到本行结束的数据,而不是一定输出一整行

fpassthru():从当前文件指针的位置到全部内容结束的数据,而不是一定输出所有的数据

但在这里你可能会有疑问:为什么输出“湖湾”后的指针位置会是17而不是15呢?按理说输出“我叫彭湖湾”这5个汉字一共占3*5 = 15个字节,多出来的17 - 15 =2字节是什么呢?

多出来的两个字节是windows下的回车换行符\n\r

\n是换行,占一字节,\r是回车,占一字节,在六中我将会介绍

六.Windows和UNIX下的回车和换行

<?php
  $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
  $fp = fopen("$DOCUMENT_ROOT/text.txt",'r');
  while(!feof($fp)){
  echo fgets($fp);
  echo ftell($fp);
  }
  fclose($fp);
?>

我们在windows下敲下回车键的时候,相当于键入了\n\r,所以“我叫彭湖湾”的15字节+“\n\r”的2字节 = 17字节

PHP 文件写入和读取操作实例详解【必看篇】

在mac下不一样的是:敲下回车键的时候,相当于只键入了\n,所以“我叫彭湖湾”的15字节+“\n”的1字节 = 16字节

PHP 文件写入和读取操作实例详解【必看篇】

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
用PHP实现将GB编码转换为UTF8
Nov 25 PHP
php adodb介绍
Mar 19 PHP
php 需要掌握的东西 不做浮躁的人
Dec 28 PHP
ecshop 批量上传(加入自定义属性)
Mar 20 PHP
php判断是否为json格式的方法
Mar 04 PHP
PHP图片裁剪函数(保持图像不变形)
May 04 PHP
thinkphp的静态缓存用法分析
Nov 29 PHP
WordPress中注册菜单与调用菜单的方法详解
Dec 18 PHP
又拍云异步上传实例教程详解
Apr 19 PHP
CodeIgniter框架数据库基本操作示例
May 24 PHP
Laravel框架实现利用监听器进行sql语句记录功能
Jun 06 PHP
laravel 出现command not found问题的解决方案
Oct 23 PHP
PHP连接MySQL数据库的三种方式实例分析【mysql、mysqli、pdo】
Nov 04 #PHP
php ZipArchive实现多文件打包下载实例
Oct 31 #PHP
Laravel框架实现抢红包功能示例
Oct 31 #PHP
laravel框架实现后台登录、退出功能示例
Oct 31 #PHP
TP5框架简单登录功能实现方法示例
Oct 31 #PHP
Laravel框架实现即点即改功能的方法分析
Oct 31 #PHP
laravel 框架实现无限级分类的方法示例
Oct 31 #PHP
You might like
使ecshop模板中可引用常量的实现方法
2011/06/02 PHP
Linux下实现PHP多进程的方法分享
2012/08/16 PHP
自制PHP框架之模型与数据库
2017/05/07 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
自适应高度框架 ----属个人收藏内容
2007/01/22 Javascript
JavaScript判断一个URL链接是否有效的实现方法
2011/10/08 Javascript
jquery乱码与contentType属性设置问题解决方案
2013/01/07 Javascript
JavaScript设置IFrame高度自适应(兼容各主流浏览器)
2013/06/05 Javascript
在Iframe中获取父窗口中表单的值(示例代码)
2013/11/22 Javascript
jquery日历控件实现方法分享
2014/03/07 Javascript
js去除浏览器默认底图的方法
2015/06/08 Javascript
JavaScript判断数组是否包含指定元素的方法
2015/07/01 Javascript
使用requestAnimationFrame实现js动画性能好
2015/08/06 Javascript
jquery实现九宫格大转盘抽奖
2015/11/13 Javascript
JavaScript高级程序设计(第三版)学习笔记1~5章
2016/03/11 Javascript
基于Vue.js实现简单搜索框
2020/03/26 Javascript
最常用的jQuery表单验证(简单)
2017/05/23 jQuery
详解node.js的http模块实例演示
2018/07/12 Javascript
获取layer.open弹出层的返回值方法
2018/08/20 Javascript
js的对象与函数详解
2019/01/21 Javascript
Vue实现返回顶部按钮实例代码
2020/10/21 Javascript
[01:14]辉夜杯战队访谈宣传片—NEWBEE.Y
2015/12/26 DOTA
[05:31]DOTA2上海特级锦标赛主赛事第三日RECAP
2016/03/05 DOTA
Python中的面向对象编程详解(下)
2015/04/13 Python
Python matplotlib绘图可视化知识点整理(小结)
2018/03/16 Python
Django添加feeds功能的示例
2018/08/07 Python
Python模块future用法原理详解
2020/01/20 Python
Python如何把Spark数据写入ElasticSearch
2020/04/18 Python
python切割图片的示例
2020/11/12 Python
html5 viewport使用方法示例详解
2013/12/02 HTML / CSS
解释一下Windows的消息机制
2014/01/30 面试题
大学生优秀的自我评价分享
2013/10/22 职场文书
一份婚庆公司创业计划书
2014/01/11 职场文书
幼儿园家长评语
2014/02/10 职场文书
财务担保书范文
2014/04/02 职场文书
Redis sentinel哨兵集群的实现步骤
2022/07/15 Redis