365bet体育在线投注_mobile.365-848.com-365bet官网手机版
做最好的网站

老旧话题:PHP 读取超大文件

2019-06-16 01:08 来源:未知

  ,反正apache或者fpm都帮我们做了,况且运行一次就销毁,根本就不存在什么内存问题。

  然而偏偏就有些个不开眼的人把这些个东西当面试题,比如总有刁民用“php读取一个10G的超大文件”当面试题来问你。当然了,作为一个和我一样的普普通通的蠢货,你听到这个问题的第一瞬间是懵逼,第二瞬间是卧槽,第三瞬间是保持结巴状态。

  “面试造火箭,入职拧螺丝”。然而,刚进来就拧螺丝的人如果能够对“PHP读取一个10G的超大文件”有所见解的话,“造火箭”也是迟早的事儿。当前为了能够来这里“拧螺丝”,还是得先搞定“读取10G文件”这个问题。

  其实,相对来说也是比较简单的事情,我们随便找一个nginx的日志文件,哪怕只有10KB,假设文件名是test.log,然后呢执行 cat test.log>

  test.log ,听我说少年,30秒左右你就该按下ctrl + C了,比如我这里,你们感受一下:

  这句英文的大概意思就是“PHP最大只给每个进程分配了128MB内存,然而你特么张口要202MB?”所以,我们修改一下php配置文件... ...

  千万不要手软,把这个参数改成1024MB,然后再次执行上面的php脚本:

  然后,我们再试试最爱的filegetcontents()函数,结果如下图:

  文件已经一次性全部被载入到内存中并将文件的每一行保存到了一个php数组中,我的机器是10G内存+256G固态硬盘,一次性载入这个202MB的文件file函数用了0.67秒钟、filegetcontents函数用了0.25秒钟(看起来filegetcontent要比file靠谱的多),不过,敲重点的我们调整了配置文件才可以读取202MB的文件,如果摆在我们面前的是一个100G的文件呢?或者说,系统提供的php配置最多之给20MB内存而你又无法修改呢?

  我们重点是如何在内存有限的机器上读取体积几百倍于内存的文件。下面,我们把memory_limit调整成16M,开启困难模式。

  202MB的文件,允许被分配的内存为16MB,所以,总体思路其实也很简单,就是一点儿一点儿地读,只要每次读取的内容小于16MB,那就一定不会有问题,首先我们感受一下一个字符一个字符读,出场嘉宾是fgetc函数:

  // 但是,打开注释后屏显字符会严重拖慢程序速度!也就是说程序运行速度可能远远超出屏幕显示速度

  虽然只有给了16M内存,但我们还是成功将202M文件全部读出来了,只不过这个运行速度是差了那么点儿意思,不大行。不能一个字母一个字母地读,这次我们一行一行地读:

  一行一行果然比一个一个字符要快很多,转念一想吧,系统分配给我们的内存上限是16MB,那我们索性一次读取一定量容量数据看看,会不会更快:

  然后我们考虑将问题升级一下,依然是上述这个202M的文件,这次我们要求读取倒数后5行的内容,这个问题看起来屌了些许,用原来的fread啥的虽然奏效但总感觉比较愚蠢。所以,现在又得引入全新的函数来解决这个问题:ftell和fseek。其中,ftell用于告知当前文件读取指针所在位置,fseek可以手动设定文件读取指针的位置。我建议大家去手册上重点观摩一下fseek函数:点击这里。

  涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、Linux、数据库、运维等。

  受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

TAG标签: php难不
版权声明:转载须经版权人书面授权并注明来源