PHP大文件读取操作
简单的文件读取,一般我们会使用 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操作。
参考文档:
《PHP7编程实战》
PHP大文件读取操作的更多相关文章
- day08 学习小测试 九九乘法表 车牌划分计算 大文件读取操作
1.1需求:读取一个100G的文件,检测文件中是否有关键字keys=['苍老师','小泽老师',"alex"], 如果有则替换成"***",并写入到另一个文件中 ...
- linux大文件读取
在生产环境中有时候可能会遇到大文件的读取问题,但是大文件读取如果按照一般的手法.如cat这种都是对io的一个挑战,如果io扛得住还好,如果扛不住 造成的后果,如服务器内存奔溃,日志损坏 方法一: se ...
- Perl中文件读取操作
Perl中文件读取操作 http://blog.csdn.net/yangxuan12580/article/details/51506216
- python大文件读取
python大文件读取 https://stackoverflow.com/questions/8009882/how-to-read-a-large-file-line-by-line-in-pyt ...
- TCP协议传输大文件读取时候的问题
TCP协议传输大文件读取时候的问题 大文件传不完的bug 我们在定义的时候定义服务端每次文件读取大小为10240, 客户端每次接受大小为10240 我们想当然的认为客户端每次读取大小就是10240而把 ...
- Java解决大文件读取的内存问题以及文件流的比较
Java解决大文件读取的内存问题以及文件流的比较 传统方式 读取文件的方式一般是是从内存中读取,官方提供了几种方式,如BufferedReader, 以及InputStream 系列的,也有封装好的如 ...
- 大文件读取方法(C#)
之前都是用StreamReader.ReadLine方法逐行读取文件,自从.NET4有了File.ReadLines这一利器,就再也不用为大文件发愁了. File.ReadLines在整个文件读取到内 ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...
- C基础 大文件读取通过标准库
引言 - 问题的构建 C大部分读取文件的时候采用fgetc, 最近在使用过程中发现性能不是很理想.都懂得fgetc每次只能读取一个字符, IO操作太频繁. 所以性能低. 本文希望通过标准库函数frea ...
随机推荐
- SpringMVC学习05(整合ssm)
5.整合SSM 环境要求 环境: IDEA MySQL 5.7.19 Tomcat 9 Maven 3.6 要求: 需要熟练掌握MySQL数据库,Spring,JavaWeb及MyBatis知识,简单 ...
- 012 PCIe总线的基础知识
一.PCIe总线的基础知识 与PCI总线不同,PCIe总线使用端到端的连接方式,在一条PCIe链路的两端只能各连接一个设备,这两个设备互为是数据发送端和数据接收端.PCIe总线除了总线链路外,还具有多 ...
- 【AI】PytorchSegmentCode
From: https://liudongdong1.github.io/ 0. 基础配置 0.1. 设置随机种子 def set_seeds(seed, cuda): ""&qu ...
- GitLabRunner命令
启动命令 gitlab-runner --debug <command> #调试模式排查错误特别有用. gitlab-runner <command> --help #获取帮助 ...
- SpringBoot启动标识修改
在src/main/resources下新建一个banner.txt ${AnsiColor.BRIGHT_RED} ///////////////////////////////////////// ...
- SpringBoot请求日期参数异常(Failed-to-convert-value-of-type-'java-lang-String'-
问题 Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; nested exce ...
- 检测一个页面所用的时间的js
window.onload = function () { var loadTime = window.performance.timing.domContentLoadedEventEnd-wind ...
- Servlet学习笔记(三)之HttpServletResponse
init() 方法中参数 ServletConfig 对象使用 通过ServletConfig 获得 ServletContext对象 使用 HttpServletRequest 与HttpServl ...
- css 文字超出俩行省略号显示
.center-titles{ overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: ...
- Install Docker Engine on CentOS 在CentOS 7 上安装Docker
Install Docker Engine on CentOS OS Requirements 系统要求 To install Docker Engine,you need a maintained ...