layout: posttitle: PHP 及 Swoole 读取大文本文件的几种方式
subtitle: PHP 及 Swoole 读取大文本文件的几种方式
date: 2019-03-01
author: he xiaodong
header-img: img/default-post-bg.jpg
catalog: true
tags:
- PHP
- Swoole
- 读取大文件

这种问题主要出现在面试题里,现实版没见过,如果有的话,可能是导入 excel 数据的时候用到,一次导入 100m+ 大小的一个 excel 文件,php 配置的 memory_limit 只有10m,如果操作

一般题目为,机器内存为2g,然后有一个 10g 的大文件,请问如何利用 php 读取,基于此需求,我导出的 sql 文件为4m ,然后几次复制粘贴,就 222m 了,然后将 php memory_limit 设置成 16m,重启服务生效

基本思维就是一个字符一个字符的读,一行一行的读,或者一块一块的读,实现也是这样的,代码如下

单字符的读

  1. <?php
  2. $begin = microtime(true);
  3. $fp = fopen('aaa.sql', "r");
  4. while(false !== ($ch = fgetc($fp))) {
  5. // 打开注释后屏显字符会严重拖慢程序速度!也就是说程序运行速度可能远远超出屏幕显示速度
  6. // echo $char.PHP_EOL;
  7. }
  8. fclose($fp);
  9. $end = microtime(true);
  10. echo "cost : " . ($end - $begin) . PHP_EOL;
  11. // 结果 22s+

单行读

  1. <?php
  2. $begin = microtime( true );
  3. $fp = fopen( 'aaa.sql', 'r' );
  4. while(false !== ($buffer = fgets($fp, 4096))) {
  5. // echo $buffer.PHP_EOL;
  6. }
  7. if (!feof($fp)) {
  8. throw new Exception('... ...');
  9. }
  10. fclose($fp);
  11. $end = microtime(true);
  12. echo "cost : " . ($end - $begin) . ' sec' . PHP_EOL;
  13. // 0.314s +

分块读

  1. <?php
  2. $begin = microtime(true);
  3. $fp = fopen('aaa.sql', 'r');
  4. while(!feof($fp)) {
  5. // 如果你要使用echo,那么,你会很惨烈...
  6. fread($fp, 10240);
  7. }
  8. fclose($fp);
  9. $end = microtime(true);
  10. echo "cost : " . ($end - $begin) . ' sec' . PHP_EOL;
  11. exit;
  12. // 0.2s+

Swoole 异步读取方法

  1. <?php
  2. use Swoole\Async;
  3. $trunk_size = 10485760;
  4. $offset = 0;
  5. $begin = microtime( true );
  6. swoole_async_read("aaa.sql", function($fileName, $content) use ($begin) {
  7. // var_dump($fileName, strlen($content));
  8. $end = microtime( true );
  9. echo "cost : " . ($end - $begin).' sec'.PHP_EOL;
  10. return true;
  11. }, $trunk_size, $offset);
  12. // 0.086s+

最终对比,Swoole 异步分块读效率最高,能够自定义每次读取块的大小,在 memory_limit 之下,就复合要求。这几种方式都能实现在有限内存内读取大文件,自行根据业务需求选择就行。其他还有利用 yield 协程读取,这样读取时间不如分块读,但内存占用会很小

参考链接:

  1. elarilty 文章
  2. Swoole 文档

最后恰饭 阿里云全系列产品/短信包特惠购买 中小企业上云最佳选择 阿里云内部优惠券