php yield 读大文件

June 6, 2018

今天来优化下读取大文件,在 PHP 读取大文件的时候,经常会出现内存不足的情况,如果文件过大的话,没法一次读取完,今天采用 yield 来实现大文件的读取。yield生成器是php5.5之后出现的,yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。yield生成器允许你 在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组。

老式读取方式

function readLocalFile($fileName)
{
  $handle = fopen($fileName, 'r');
  $lins = [];
  while (!feof($handle)) {
      $lines[] = fgets($handle);
  }
  fclose($handle);
  return $lines;
}

yield 读取方式

使用 yield 的特性,来读取大文件

function readYieldFile($fileName)
{
  $handle = fopen($fileName, 'r');
  while (!feof($handle)) {
      yield fgets($handle);
  }
  fclose($handle);
}

辅助函数

为了便于测试,我们写一个读取内存的辅助函数

function formatBytes($bytes)
{
  if ($bytes < 1024) {
      return $bytes . "b";
  } else if ($bytes < 1048576) {
      return round($bytes / 1024, 2) . "kb";
  }
  return round($bytes / 1048576, 2) . 'mb';
}

测试

我这里准备了一个 7M 大小的文本文件来做测试。

# 第一种
readLocalFile('./all.txt');
echo formatBytes(memory_get_peak_usage());  // 结果为 7.59mb

# 第二种
$lines = readYieldFile('./all.txt');
foreach ($lines as $row) {}
echo formatBytes(memory_get_peak_usage());  // 结果为 137.79kb



转:https://www.ooovip.cn/index.php/archives/57/

今天来优化下读取大文件,在 PHP 读取大文件的时候,经常会出现内存不足的情况,如果文件过大的话,没法一次读取完,今天采用 yield 来实现大文件的读取。yield生成器是php5.5之后出现的,yield提供了一种更容易的方法来实现简单的迭代对象,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。yield生成器允许你 在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组。

老式读取方式

function readLocalFile($fileName)
{
  $handle = fopen($fileName, 'r');
  $lins = [];
  while (!feof($handle)) {
      $lines[] = fgets($handle);
  }
  fclose($handle);
  return $lines;
}

yield 读取方式

使用 yield 的特性,来读取大文件

function readYieldFile($fileName)
{
  $handle = fopen($fileName, 'r');
  while (!feof($handle)) {
      yield fgets($handle);
  }
  fclose($handle);
}

辅助函数

为了便于测试,我们写一个读取内存的辅助函数

function formatBytes($bytes)
{
  if ($bytes < 1024) {
      return $bytes . "b";
  } else if ($bytes < 1048576) {
      return round($bytes / 1024, 2) . "kb";
  }
  return round($bytes / 1048576, 2) . 'mb';
}

测试

我这里准备了一个 7M 大小的文本文件来做测试。

# 第一种
readLocalFile('./all.txt');
echo formatBytes(memory_get_peak_usage());  // 结果为 7.59mb

# 第二种
$lines = readYieldFile('./all.txt');
foreach ($lines as $row) {}
echo formatBytes(memory_get_peak_usage());  // 结果为 137.79kb



转:https://www.ooovip.cn/index.php/archives/57/