当前位置: 首页 > 后端技术 > PHP

老话题:PHP读取超大文件

时间:2023-03-29 14:57:52 PHP

作为一个常年耕耘凝乳的PHPer,关注内存是不可能的。反正apache或者fpm都可以帮我们搞定,运行一次就销毁了。什么都没有。内存问题。但是,有些盲人把这些东西当作面试题。比如总有骗子把“php读取一个10G的大文件”当成面试题来问你。当然,像我这样一个普通的白痴,听到这个问题第一眼是懵的,第二眼是撒谎,第三眼是口吃。“面试造火箭,入门螺丝钉。”不过,如果刚进来拧螺丝的人能对“PHP读取一个10G的大文件”有所感悟,那迟早是“造火箭”的事情。目前要想在这里“拧螺丝”,还是得先解决“读取10G文件”的问题。想要读取10G的文件,首先得有一个10G的文件……其实还是比较简单的。我们找一个nginx日志文件,哪怕只有10KB,假设文件名是test.log,然后执行“cattest.log>>test.log”,听我说小子,你应该按ctrl+C大概30秒,比如这里,你感觉:202MB,作为一个实验Demonstration已经足够有趣了。真的可以创建一个10G的文件吗?首先,我们尝试利用php的文件功能进行杀戮。你可以感受一下:;保存为test.php,然后在命令行执行,结果如下图:这句话英文大概意思是“PHP只是为每个进程最多分配128MB的内存,但是为什么需要202MB?”那么,我们来修改一下php的配置文件吧……不要手软,把这个参数改成1024MB,然后再执行上面的php脚本:然后,再试试我们最喜欢的file_get_contents()函数,结果如下:文件一次性加载到内存中,文件的每一行都保存在一个php数组中。我的机器是10G内存+256G固态硬盘,用file函数一次加载202MB的文件用了0.67秒,用file_get_contents函数用了0.25秒(好像file_get_content比file靠谱多了),但是我们在我们可以读取之前调整配置文件。拿一个202MB的文件来说,如果我们面前有一个100G的文件呢?也就是说,系统提供的php配置限制为20MB内存,不能修改?我们的重点是如何在内存有限的机器上读取比内存大数百倍的文件。接下来,我们将memory_limit调整为16M,并开启hard模式。对于202MB的文件,允许分配的内存为16MB。所以,整体的思路其实很简单,就是一点一点的去读。只要每次读取的内容小于16MB,就没有问题。首先我们感觉Readonecharacterattime,guest是fgetc函数:0){while($ch!="\n"){fseek($fp,$pos,SEEK_END);$ch=fgetc($fp);$pos--;}$ch='';$content.=fgets($fp);$line--;}echo$content;exit;其中test1.log文件的内容如下:aabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffffbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeffffffffffffffffffffffffffffffff11111111112222222222保存文件并运行,结果如下图所示: