当前位置: 首页 > news >正文

PHP流式处理与生成器应用

PHP流式处理与生成器应用

处理大文件或大数据集时,一次性加载到内存会导致内存溢出。PHP的生成器和流式处理可以解决这个问题。今天说说怎么用生成器处理大数据。

生成器用yield关键字,可以在不生成整个数组的情况下进行迭代。每次迭代到yield时,函数会暂停并保存状态,下次迭代再继续。

```php
// 生成器:逐行读取大文件
function readLargeFile(string $path): Generator
{
$handle = fopen($path, 'r');
if ($handle === false) {
throw new RuntimeException("无法打开文件: $path");
}

$lineNumber = 0;
while (($line = fgets($handle)) !== false) {
$lineNumber++;
yield $lineNumber => trim($line);
}

fclose($handle);
}

// 使用生成器
$file = '/tmp/large_file.txt';
file_put_contents($file, implode("\n", range(1, 1000000)));

$start = memory_get_usage(true);
foreach (readLargeFile($file) as $num => $line) {
if ($num % 100000 === 0) {
echo "已处理 {$num} 行\n";
}
}
echo "内存使用: " . (memory_get_usage(true) - $start) / 1024 . " KB\n";
?>
```

生成器可以用于生成数据,而不需要预先创建数组:

```php
// 生成所有数据的生成器
function generateRange(int $start, int $end, int $step = 1): Generator
{
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}

// 斐波那契数列生成器
function fibonacci(int $limit): Generator
{
$a = 0;
$b = 1;
for ($i = 0; $i < $limit; $i++) {
yield $a;
[$a, $b] = [$b, $a + $b];
}
}

echo "斐波那契前10: ";
foreach (fibonacci(10) as $num) {
echo "$num ";
}
echo "\n";

// 分页数据生成器
function paginateGenerator(callable $fetcher, int $perPage = 100): Generator
{
$page = 1;
while (true) {
$items = $fetcher($page, $perPage);
if (empty($items)) break;

foreach ($items as $item) {
yield $item;
}

if (count($items) < $perPage) break;
$page++;
}
}

// 模拟从数据库分页查询
function fetchFromDb(int $page, int $perPage): array
{
$start = ($page - 1) * $perPage;
if ($start >= 1000) return [];

return array_map(fn($i) => "item_" . ($start + $i), range(1, $perPage));
}

$count = 0;
foreach (paginateGenerator('fetchFromDb', 50) as $item) {
$count++;
}
echo "生成器获取了 {$count} 条数据\n";
?>
```

生成器还可以用作协程,实现简单的协作式多任务:

```php
class Task
{
private Generator $coroutine;
private string $name;

public function __construct(string $name, Generator $coroutine)
{
$this->name = $name;
$this->coroutine = $coroutine;
}

public function run(): bool
{
if ($this->coroutine->valid()) {
echo "运行任务: {$this->name}\n";
$this->coroutine->next();
return true;
}
return false;
}

public function isFinished(): bool
{
return !$this->coroutine->valid();
}
}

class Scheduler
{
private array $tasks = [];

public function add(Task $task): void
{
$this->tasks[] = $task;
}

public function run(): void
{
while (!empty($this->tasks)) {
$task = array_shift($this->tasks);
$task->run();

if (!$task->isFinished()) {
$this->tasks[] = $task;
} else {
echo "任务完成\n";
}
}
}
}

$scheduler = new Scheduler();

$scheduler->add(new Task('A', (function () {
yield;
echo "任务A步骤2\n";
yield;
echo "任务A步骤3\n";
})()));

$scheduler->add(new Task('B', (function () {
yield;
echo "任务B步骤2\n";
yield;
})()));

$scheduler->run();
?>
```

管道处理可以把多个生成器连接起来,形成处理流水线:

```php
function generateNumbers(int $count): Generator
{
for ($i = 1; $i <= $count; $i++) {
yield $i;
}
}

function filterEven(Generator $input): Generator
{
foreach ($input as $value) {
if ($value % 2 === 0) {
yield $value;
}
}
}

function multiply(Generator $input, int $factor): Generator
{
foreach ($input as $value) {
yield $value * $factor;
}
}

function limit(Generator $input, int $count): Generator
{
$i = 0;
foreach ($input as $value) {
if ($i++ >= $count) break;
yield $value;
}
}

// 管道:生成数字 -> 过滤偶数 -> 乘以3 -> 取前5个
$pipeline = limit(
multiply(
filterEven(
generateNumbers(100)
),
3
),
5
);

echo "管道处理结果: ";
foreach ($pipeline as $value) {
echo "$value ";
}
echo "\n";
?>
```

生成器的内存优势很明显。生成一百万个数字的数组会占用几十MB内存,而生成器只占几十字节。在处理大数据、大文件、大量数据库记录时,生成器是非常有用的工具。

http://www.gsyq.cn/news/1470475.html

相关文章:

  • 炉石传说脚本自动化:从基础操作到智能决策的完整指南
  • 解决AI改文件翻车难题:一套自研沙盒版本机制,让浏览器Agent拥有后悔药
  • 2026年装饰设计品牌企业排名:高性价比的名匠装饰推荐 - myqiye
  • 2026昆明配眼镜推荐去哪家,五家门店全方位实测对比 - 配眼镜新资讯
  • YOLOv11涨点改进| TGRS 2026 |特征融合改进篇| 引入DFAM差异特征频域注意力融合模块,发论文热点创新,强化细节与边缘特征,提高对小目标和弱特征目标的感知能力,YOLOv11有效涨点
  • 2026北京老酒回收机构评测:北京名酒回收/北京洋酒回收/北京老酒回收回收/北京茅台回收/北京闲置酒水回收/北京专业洋酒回收/选择指南 - 优质品牌商家
  • 数组访问、类型转换与循环翻译:龙书习题实战中的三个编译‘硬骨头’怎么啃?
  • PHP开放平台与OAuth认证服务
  • 5分钟上手BilibiliDown:免费B站视频下载器全攻略
  • 异辛基三乙氧基硅烷技术解析与合规供应选型指南:环氧灌浆料/硅烷浸渍剂/硅烷膏体/自密实混凝士/铝酸盐无机防腐砂浆/选择指南 - 优质品牌商家
  • 谁能拒绝一枚月光做成的耳机✨
  • 2026年近期济宁地区寻求高性价比食品输送带?这家制造商值得关注 - 2026年企业资讯
  • 别再死记硬背Node2Vec公式了!用Python+PyTorch手搓一个随机游走节点嵌入(附完整代码)
  • 3天掌握芋道源码企业级框架:从零搭建到实战开发的完整指南
  • Gemini会话留存率低于行业均值37%?5步动态权重调优法,72小时内拉升至81.4%(含Prometheus监控模板)
  • 2026年上海增量式直线位移传感器市场深度解析:如何选择优质供应商 - 2026年企业资讯
  • 用Python复现通达信Winner函数:手把手教你估算A股筹码分布与获利盘比例
  • 免费解锁Wand专业版:终极完整指南与远程控制教程
  • 成都危险品物流仓储核心技术规范与合规实操指南:成都危险品物流仓储/成都危险品贮存/成都危险货物危险品仓库/危险化学品储存/选择指南 - 优质品牌商家
  • 从‘过零点’到‘比特流’:手把手教你用Python仿真复现FSK软件解调全过程(含信号可视化)
  • 实战演练,基于快马平台jdk17环境快速搭建restful api微服务
  • 非参数核聚类与老虎机反馈:理论与应用解析
  • 基于STM32与AD9851的双通道可编程波形发生器,支持基波+5次谐波叠加及三种基础波形输出
  • 2026年Q2嘉兴奢侈品回收实测:嘉兴名鉴钟表有限公司联系/嘉兴首饰回收/嘉兴奢侈品回收/嘉兴工艺美术品回收/嘉兴黄金回收/选择指南 - 优质品牌商家
  • 教资科三知识点汇总|初中高中各学科重点笔记整理
  • Windows + Trae 安装使用 CodeGraph 完整指南
  • 鸿蒙开发--CANNKit-AscendC-sobel
  • 保姆级教程:Halcon 18.11.0.1 Windows版从下载到激活全流程(含GigE驱动安装)
  • AI辅助开发:利用快马平台实现智能自适应的sweezy-cursors动画
  • SMT贴片加工锡膏储存和使用注意事项