【PHP】文件写入和读取详解

news2024/11/15 18:53:47

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

1.通过fopen方法打开文件:$fp =fopen(/*参数,参数*/),fp为Resource类型

2.进行文件读取或者文件写入操作(这里使用的函数以1中返回的$fp作为参数)

3.   调用fclose($fp)关闭关闭文件

二:使用fopen方法打开文件

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

<1>fopen的第一个参数为文件路径

写文件路径的方式:1绝对路径,2相对路径

1绝对路径:

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

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

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

复制

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

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

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

复制

运行后打开C:/wamp64/www/text.txt,发现文件内容并没有改变,说明由于没有设置相应的权限,操作被忽略了

关于打开模式的网络资料,我想大家最可能找到的是这张表:(图来自W3C)

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

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

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

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

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

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

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

采用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”覆盖了:

采用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);
?>

复制

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

运行多次后:

•采用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”这段新文本

【注意】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了

读取文件

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

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

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);//关闭文件
?>

复制

运行:

【注意】:无论是按文本格式输入输出还是按二进制格式输出,fgetc()每次获取的是一个字节而不是一个字符

上面的例子中我们是逐个输出,现在让我们只做一次输出,看看结果怎样:

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

复制

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

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

复制

运行结果:

改成:

echo fread($fp, 6);

复制

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

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);//关闭文件
?>

复制

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

【注意】在UTF-8编码下汉字3字节,字母1字节

下面我修改上面的一行,代码,使获取的每一行最大字符数为3(也即字节数为9)

$line = fgets($fp,10);

复制

Demo:

【注意】:这里我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);
?>

复制

运行结果:

【注意】这里需要注意一点的是,我们并没有从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/>";
    }
?>

复制

【注意】:这里我们并不需要写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:

所以我们需要正确理解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字节

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/674047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python网络爬虫基础进阶到实战教程

文章目录 认识网络爬虫HTML页面组成Requests模块get请求与实战效果图代码解析 Post请求与实战代码解析 发送JSON格式的POST请求使用代理服务器发送POST请求发送带文件的POST请求 Xpath解析XPath语法的规则集&#xff1a;XPath解析的代码案例及其详细讲解&#xff1a;使用XPath解…

macOS Sonoma 14 beta 2 (23A5276g) ISO、IPSW、PKG 下载

macOS Sonoma 14 beta 2 (23A5276g) ISO、IPSW、PKG 下载 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Windows 和 Linu…

【致敬未来的攻城狮计划】打卡2:keil 程序下载尝试

下载 终于考完试了&#xff0c;然而攻城狮的截止期限也快到了QAQ&#xff0c;得尽快水&#xff08;划掉&#xff09;写几篇文章了&#xff01; 先争取可以成功下载一个空的程序。 先对上一篇文章下载 DFP 也就是 keil MDK Software Packs 做一个补充。我们要下载的是 RA_DFP…

[进阶]TCP通信综合案例:群聊

代码演示如下&#xff1a; 客户端&#xff1a; public class Client {public static void main(String[] args) throws Exception{System.out.println("客户端开启&#xff01;");//1.创建Socket对象&#xff0c;并同时请求与服务端程序的连接。Socket socket new…

网线制作实验

计算机网络综合实训 网线制作 所在院系 计算机与信息工程学院 学科专业名称 计算机科学与技术 导师及职称 柯宗武 教授 提交时间 2023.4.30 计算机网络综合实训报告 一、实验目的 1、掌握三类UTP线缆的制作和测试方法 2、了解三类UTP线缆的作用及布线方式 二、实验内容 1、局…

第二章 进程的描述与控制

目录 一、进程的概念、组成、特征 1.1 进程的概念 1.1.1 程序 1.1.2 进程 1.2 进程的组成 1.3 进程控制块PCB 1.4 进程的特征 二、进程的状态与转换 2.1 进程的状态 2.2 创建态、就绪态 2.3 运行态 2.4 阻塞态 2.5 终止态 2.6 进程状态的转换 2.7 进程的组织 三…

【C++篇】C++字符串:标准库string类

友情链接&#xff1a;C/C系列系统学习目录 知识总结顺序参考C Primer Plus&#xff08;第六版&#xff09;和谭浩强老师的C程序设计&#xff08;第五版&#xff09;等&#xff0c;内容以书中为标准&#xff0c;同时参考其它各类书籍以及优质文章&#xff0c;以至减少知识点上的…

python3.9 安装 pyspider

安装pyspider pip install pyspider 直接报错 Please specify --curl-dir/path/to/built/libcurl 于是从PythonLibs官网 中获取依赖并自行下载到本地 下载与3.9对应的 执行安装 pip install D:\下载\ad3-2.2.1-cp39-cp39-win32.whl 安装成功之后 执行 pip install p…

1748_Perl中使用通配符处理文件

全部学习汇总&#xff1a; GreyZhang/perl_basic: some perl basic learning notes. (github.com) 使用通配符处理文件一般是用于文件的拷贝、删除以及对文件逐个分析等功能。在Perl中遇到的相应的功能基本上也是如此。通配符匹配处理文件&#xff08;文件名&#xff09;需要使…

前端JavaScript入门-day01

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 JavaScript 介绍 1 JavaScript 是什么 1. JavaScript &#xff08;是什么&#xff1f;&#xff09; 2. 作…

H. Don‘t Blame Me(DP)

Problem - 1829H - Codeforces 很遗憾&#xff0c;这道题目的出题人没有想到一个有趣的故事&#xff0c;所以他只是让你解决以下问题。 给定由n个正整数组成的数组a&#xff0c;计算具有子序列中元素的按位AND在其二进制表示中恰好有k个设置位的非空子序列的数量。答案可能很大…

Winwebmail搭建邮件服务器

配置环境 角色系统IP地址DNS邮件服务器WindowServer2016192.168.1.1/24192.168.1.1客户端1Window10192.168.1.10/24192.168.1.1客户端2Window10192.168.1.20/24192.168.1.1 Winwebmail介绍 WinWebMail是安全高速的全功能邮件服务器&#xff0c;融合强大的功能与轻松的管理为…

macOS Ventura 13.4.1 (22F82|22F2083) 正式版发布,ISO、IPSW、PKG 下载

macOS Ventura 13.4.1 (22F82|22F2083) 正式版发布&#xff0c;ISO、IPSW、PKG 下载 本站下载的 macOS Ventura 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安…

C++ 指针常量与常量指针

指针常量与常量指针的翻译就好比机器学习中Regularization翻译成正则化一样&#xff0c;讲真&#xff0c;正则化这个说法确实要比规则化显得高端些&#xff0c;但是到了理解的时候&#xff0c;还是要按照规则化理解。 指针常量与常量指针这个概念是一样的&#xff0c;英文里没…

【STM32】软件I2C(支持多字节)

I2C简介 I2C总线是一种串行、半双工的总线&#xff0c;主要用于近距离、低速的芯片之间的通信。I2C总线有两根双向的信号线&#xff0c;一根数据线SDA用于收发数据&#xff0c;一根时钟线SCL用于通信双方时钟的同步。 在一个i2c通讯总线中&#xff0c;可连接多个i2c通讯设备&a…

Linux国产操作系统,UCA-系统工程师学习必备技能,系统状态查询和进程管理,uname命令last命令 top命令和 ps命令 kill命令

目录 ​编辑 1.系统状态查询 1. 1.uname命令 1.2. last命令 1.3. top命令 2.进程管理 2.1. ps命令 2.2. kill命令 1.系统状态查询 1. 1.uname命令 rootuos~#: uname rootuos~#: uname -r 4.19是内核&#xff0c;0-6-amd64是架构。 rootuos~#: uname -a eagle操作系统的…

【深入浅出 Spring Security(十一)】授权原理分析和持久化URL权限管理

授权原理分析和持久化URL权限管理 一、必须知道的三大组件&#xff08;Overview&#xff09;二、FilterSecurityInterceptor 源码分析SecurityMetadataSource 分析 三、自定义 FilterSecurityMetadataSource 对象&#xff08;实战&#xff09;自定义表CustomSecurityMetadataSo…

【C++】构造函数调用规则

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01;时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 1、缘起 &#xff08;1&#xff09;默认情况下&#xff0c;C 编译器至少给一个类添加 3 个函数 ① 默认构造函数&#xff08;无参&#…

多无人车自动编队

matlab2016b可运行 Kaveh Fathian - Distributed Formation Control of Cars with Collision Avoidance (google.com)

极致呈现系列之:Echarts桑基图的流动旋律

目录 什么是桑基图桑基图的特点及应用场景Echarts中桑基图的常用属性Vue3中创建桑基图美化桑基图 在各种复杂系统中&#xff0c;我们经常需要了解不同流量之间的关系和流动情况。这种信息的可视化呈现对于我们理解系统的结构和转移过程至关重要。桑基图作为一种强大的可视化工具…