简单的文件读取,一般我们会使用 file_get_contents() 这类方式来直接获取文件的内容。不过这种函数有个严重的问题是它会把文件一次性地加载到内存中,也就是说,它会受到内存的限制。因此,加载大文件的时候是绝对不能使用这种方式的。我们还是先看看这种方式加载的例子。

// 普通的文件读取 一个2.4G的SQL导出文件
$fileName= './2020-02-23.sql'; // file_get_contents
$fileInfo = file_get_contents($fileName);
// Fatal error: Allowed memory size of 134217728 bytes exhausted // file
$fileInfo = file($fileName);
// Fatal error: Allowed memory size of 134217728 bytes exhausted // fopen + fread
$fileHandle = fopen($fileName, 'r');
$fileInfo = fread($fileHandle, filesize($fileName));
// Fatal error: Allowed memory size of 134217728 bytes exhausted

上述三种形式的文件加载读取方式都是不能加载这么大的文件的,当然,你也可以修改 php.ini 中的相关配置让他们能够加载成功,但我们并不推荐这样使用,毕竟内存资源相比硬盘资源还是要宝贵的多。

以下的方式是可以直接读取这种大文件的:

// readfile 只能直接输出
echo readfile($fileName); // fopen + fgetc 如果单
$fileHandle = fopen($fileName, 'r');
// 输出单字符直到 end-of-file
while(!feof($fileHandle)) {
echo fgetc($fileHandle);
}
fclose($fileHandle); // SplFileObject
$fileObject = new SplFileObject($fileName, 'r');
while(!$fileObject->eof()){
echo $fileObject->fgetc();
}

第一个 readfile() ,读取文件后就直接打印了,不能进行其他操作,适用于直接显示大文件内容时使用。

第二个 fopen() 配合 fgetc() 或 fgets() 是读取这种大文件的标配。fopen() 获取文件句柄,fgetc() 按字符读取,fgets() 按行读取。像这个 mysqldump 出来的文件,一行也可能非常的大,所以我们就只能直接按字符读取。

第三个是SPL扩展库为我们提供的面向对象式的 fopen() 操作,建议新的开发中如果有读取大文件的需求最好使用这种形式的写法,毕竟SPL函数库已经是PHP的标准函数库了,而且面向对象的操作形式也更加的主流。

上面三种读取方式都有一个要注意的点是,我们将大文件读取后不应该再保存到变量中,应该直接打印显示、入库或者写到其他文件中。因为直接读取到一个变量中就和前面的直接读取到内存的方式一样了,那还不如直接去修改下 php.ini 的配置然后使用最上方的方式直接读取到内存方便。还是那句话,内存留给真正需要它的地方,这种大文件,最好还是进行硬盘的IO操作。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202003/source/PHP%E5%A4%A7%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96%E6%93%8D%E4%BD%9C.php

参考文档:

《PHP7编程实战》

PHP大文件读取操作的更多相关文章

  1. day08 学习小测试 九九乘法表 车牌划分计算 大文件读取操作

    1.1需求:读取一个100G的文件,检测文件中是否有关键字keys=['苍老师','小泽老师',"alex"], 如果有则替换成"***",并写入到另一个文件中 ...

  2. linux大文件读取

    在生产环境中有时候可能会遇到大文件的读取问题,但是大文件读取如果按照一般的手法.如cat这种都是对io的一个挑战,如果io扛得住还好,如果扛不住 造成的后果,如服务器内存奔溃,日志损坏 方法一: se ...

  3. Perl中文件读取操作

    Perl中文件读取操作 http://blog.csdn.net/yangxuan12580/article/details/51506216

  4. python大文件读取

    python大文件读取 https://stackoverflow.com/questions/8009882/how-to-read-a-large-file-line-by-line-in-pyt ...

  5. TCP协议传输大文件读取时候的问题

    TCP协议传输大文件读取时候的问题 大文件传不完的bug 我们在定义的时候定义服务端每次文件读取大小为10240, 客户端每次接受大小为10240 我们想当然的认为客户端每次读取大小就是10240而把 ...

  6. Java解决大文件读取的内存问题以及文件流的比较

    Java解决大文件读取的内存问题以及文件流的比较 传统方式 读取文件的方式一般是是从内存中读取,官方提供了几种方式,如BufferedReader, 以及InputStream 系列的,也有封装好的如 ...

  7. 大文件读取方法(C#)

    之前都是用StreamReader.ReadLine方法逐行读取文件,自从.NET4有了File.ReadLines这一利器,就再也不用为大文件发愁了. File.ReadLines在整个文件读取到内 ...

  8. 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射

    内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...

  9. C基础 大文件读取通过标准库

    引言 - 问题的构建 C大部分读取文件的时候采用fgetc, 最近在使用过程中发现性能不是很理想.都懂得fgetc每次只能读取一个字符, IO操作太频繁. 所以性能低. 本文希望通过标准库函数frea ...

随机推荐

  1. KNeighborsClassifier()的参数无效错误

    KNeighborsClassifier()的参数无效错误 写在前面:如果对自己英语拼写很自信,可以不用往下看了,我就是拼写错误 错误提示 Invalid parameter n_neightbors ...

  2. sqli-labs lesson5-6 布尔盲注 报错注入 延时注入

    LESSON 5: 典型的布尔盲注. 盲注:sql注入过程中,sql语句的执行结果不回显到前端,这个时候就只能用一些别的方法进行判断或者尝试,这个判断或者尝试就叫做盲注.盲注又分为:1.基于布尔SQL ...

  3. 题解 P4449 于神之怒加强版

    这道题算是我完完整整推的第一道题,写篇题解纪念一下. 题目 废话不多说,直接开始推式子(给新手准备,过程较详细,大佬可自行跳步),以下过程中均假设 \((n\le m)\),\([d=1]\) 类似于 ...

  4. 【IDE】Sublime Text 3 使用配置

    1 安装 首先现在安装Sublime Text 3,直接官网下载(http://www.sublimetext.com/3),也可以在其他地方下载,安装完成后进行破解 菜单栏Help - Enter ...

  5. Kafka源码篇 --- 小白也能看懂的Producer的初始化及元数据获取流程

    最近在研究kafka的源码,发现有些小伙伴的源码写的很不错,就想转载一下,让更多的人知道和学习一下. https://blog.csdn.net/weixin_43167418/article/det ...

  6. [转]VRRP协议详解

    原文地址:VRRP协议详解 文中涉及缩略语 缩略语 英文全名 中文解释 VRRP Virtual Router Redundancy Protocol 虚拟路由器冗余协议 NQA Network Qu ...

  7. 面试必问题:JS防抖与节流

    摘要:防抖与节流可谓是面试常见,其实很好理解,下面带你分分钟了解防抖与节流的基本思想与写法~ 本文分享自华为云社区<JS防抖与节流快速了解与应用>,作者:北极光之夜. . 一.速识防抖: ...

  8. UVA1620 Lazy Susan(结论证明)

    结论: 当 \(n\geq 6\) 时,若 \(n\) 是奇数且输入序列的逆序对数是奇数,则无解,否则有解. 当 \(n=4\) 或 \(n=5\) 时,答案个数及其有限,只有这个环是 \(1\) 到 ...

  9. ES6扩展——模板字符串

    ${ } 模板字符串占位符 需要用反引号` ` 1.模板字符串 `${变量}` const xiaoming = { name:'xiaoming', age:14, say1:function(){ ...

  10. 设置 Qt GUI程序 printf输出到独立控制台