php并发取源码,PHP读取大文件源码示例-Swoole多进程读取大文件

PHP读取大文件源码示例,通过PHP读取过大、超大型文件的思路及解决方案。

在日常读取文件时,若文件 不是很大,通常使用file_get_contents,将内容一次性载入的变量中,也可以远程加载网页或者远端文件。

若加载超过PHP限制的内存大小,或者超过本机内存大小的文件进程就会报错或者崩掉。

为了解决这个问题,我们采用使用完毕并释放的原则来读取大文件。

单线程读入

如果不考虑多线程的情况下,单线程读取大文件采用while fread就可以实现。

如下代码

$handle = fopen("./big.txt", "rb");

while (!feof($handle)) {

$contents = fread($handle, 8192);

// 业务处理

unset($contents); // 释放掉变量

}

fclose($handle);

feof是判断是否到文件尾,如果没有到文件尾,则会一直while循环,并执行读取操作。每次读取8192字节,然后使用过后将其释放掉。

往往很多文件并不是一行的,有多行内容。需要将每行内容读取出来当做一条数据处理,也可以使用fgets。

即如下代码:

$handle = fopen("./big.txt", "rb");

while (!feof($handle)) {

$contents = fgets($handle, 1024);

// 业务处理

unset($contents); // 释放掉变量

}

fclose($handle);

这里的fgets第二个参数,默认为1024字节。即默认读取一行数据,如果一行数据小于1024字节,则完整读取。如果超出1024字节,则只取前1024字节。遇到换行符"\n"或者"\r\n"或者结束符会停止读取。

如果遇到变态的文件,很多行都只有1000长度,某一行有8000长度,如果在不清楚的情况下,就很难掌控,若要完整读取就需要指定读取的最大字节,8000才能将每一行完整读取。

还有一种方法就是自己处理换行符。默认读取1024字节,然后放置到内存中,使用过后再将其释放。这种操作很节省内存,但是在逻辑处理上需要自己处理换行符。

如,读取1024字节,没有换行符,则保存数据继续读取。再读取1024字节,判断其中是否有换行符,如果有则处理最开始到换行符中的数据。再将剩下的数据保存,等待下一次读取,直到整个文件读取完毕。

$handle = fopen("./big.txt", "rb");

$contents = "";

while (!feof($handle)) {

$contents .= fread($handle, 8192);

// 判断读取到的内容是否包含换行符,包含则进入循环体

while(strpos($contents, "\n") !== false){

$eol_pos= strpos($contents, "\n");

$line = substr($contents, 0, $eol_pos);

// $line为一行的数据,进行业务处理,并释放

unset($line);

$contents = substr($eol_pos, 0);// 将剩余内容放置到变量中以供下次使用

}

}

fclose($handle);

多线程读取

PHP默认没有多线程,这里可以采用多进程的方式实现,或者swoole的多进程来实现。

例如读取一个8GB文件,分8个线程,每个线程读取1GB数据内容。或者更多线程进行拆分工作内容。

获取文件大小

首先第一步,就是获取整个文件的体积大小,然后计算每个线程应该负责处理的一部分内容。

function length($filename)

{

$handle = fopen($filename, "rb");

$currentPos = ftell($handle);

fseek($handle, 0, SEEK_END);

$length = ftell($handle);

fseek($handle, $currentPos);

// $length 文件总长度

return $length;

}

echo length("./big.txt");

处理逻辑实现过程

这里主要说明下作了哪些内容,首先是设定分配总的线程数。然后根据设置的线程数,计算每个线程要读取的数据大小,即从哪里开始读,读到哪里结束。

然后必定会出现拆分后,读到不完整行的情况,在这里来解决这种前半行或者后半行的意外情况。

解决逻辑就是,假设线程开始的读取位置在某一行的中间,我们一个字符向前移动,移动到上个换行符(也可能是最开始)即可获取到整行文本内容。

处理掉残行数据之后,使用yield来传递数据给业务处理。

$filename = "./big.txt";

$maxProcess = 8;// 分配8个线程

$length = length($filename);

$singleProcessLength = ceil($length / $maxProcess);

// 线程负责读取的内容

function processRead($filename, $index, $singleProcessLength)

{

$fh = fopen($filename, 'r');

$beginPos = $index * $singleProcessLength;

//结束位置=线程序列*线程处理数据长度+线程处理数据 - 1 (长度转指针,实际结束指针小于结束长度)

$endPos = $index * $singleProcessLength + $singleProcessLength - 1;

fseek($fh, $beginPos);

echo '线程:' . $index . ',起始位置:' . $beginPos . ',结束位置:' . $endPos . PHP_EOL;

//移动到上个\n 以便首次顺利获取整行内容

while (fseek($fh, -1, SEEK_CUR) === 0) {

if (fread($fh, 1) == "\n" || ftell($fh) <= 0) {

break;

}

fseek($fh, -1, SEEK_CUR);

}

echo '线程:' . $index . ',移动完毕!!!!!' . PHP_EOL;

//整行读取数据

//结束时位置超过预计结束位置是正常状况,fgets 读取一整行内容

//预计结束位置可能在行内,所以产生不同结果。

while (ftell($fh) <= $endPos && !feof($fh)) {

yield $raw = fgets($fh);

}

echo '进程' . $index . '结束时 指针位置:' . ftell($fh) . ', 应该到:' . $endPos . PHP_EOL;

fclose($fh);

}

foreach(range(0,$maxProcess - 1) as $index){

// 多线程采用多线程的方式创建,这里采用yield回调。

foreach(processRead($filename, $index, $singleProcessLength) as $value){

// $value为每一行的内容,处理后释放

unset($value);

}

}

如上所述就是PHP的大文件读取解决方案,大部分用于多线程读取大文件场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/554496.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QQ如何设置会话窗默认使用腾讯视频播放视频文件

小编给大家整理了大量腾讯视频的使用方法和问题解决办法&#xff0c;这篇文章依然非常有价值&#xff0c;如果你遇到“QQ如何设置会话窗默认使用腾讯视频播放视频文件”方面的问题&#xff0c;赶紧看看吧。腾讯视频播放器推荐精准&#xff0c;越用越懂你&#xff0c;分秒就能计…

mysql 定期备份策略,MySQL--3--mysqldump备份策略

参考地址&#xff1a;http://doc.mysql.cn/mysql5/refman-5.1-zh.html-chapter/database-administration.html#backup-strategy-example5.9 备份策略在my.inf中启动二进制日志&#xff0c;用--log-bin[file_name]选项启动时&#xff0c;mysqld写入包含所有更新数据的SQL命令的日…

兔弟弟和月亮婆婆

有一天晚上&#xff0c;兔弟弟不想睡觉。他要去找小青蛙玩。兔妈妈摇摇头说&#xff1a;“乖孩子&#xff0c;睡觉吧。明天早些起来&#xff0c;找小青蛙玩去!” 兔弟弟不听妈妈的话&#xff0c;他说&#xff1a;“我要去&#xff0c;我要去&#xff0c;我不要睡觉!”兔妈妈不…

matlab问题利用M文件比较两个数大小,Matlab中写M文件及调用

1题、自然数n的阶乘function ylilu_fact(n)nfloor(n);%如果是小数,向下取整至整数y1;if n>1 %这里负数,0的阶乘都将得到1for i1:nyy*i;endend2题、n中取m的组合function ylilu_cnm(n,m)y1;if (n>m && n>0 & m>0)mmin(n-m,m);for i1:myy*(n-i1)/i;ende…

小老鼠艾尔的新毯子

今天分享一则非常暖心的故事《小老鼠艾尔的新毯子》最开心的事不是拥有什么宝贝&#xff0c;而是因为你的行动让别人开心&#xff0c;那才是最大的快乐。 小老鼠艾尔有一次在外出的时候&#xff0c;捡到一条漂亮的毛毯&#xff0c;实际上那是一个小姑娘的袜子&#xff0c;是她…

matlab 展开多项式,matlab中freqz的用法以及多项式的展开

对于一个变量a&#xff0c;matlab中定义需要这样 syms a&#xff1b;定义之后就可以写由变量组成的式子&#xff0c;比如 c(1a^-1)^5;可以用expand(c) 就能把c展开成多项式&#xff0c;每一项的系数就可以看到。freqz的用法MATLAB提供了专门用于求离散系统频响特性的函数freqz(…

IE11浏览器一个窗口打开多个页面设置方法

ie1166760一个窗口打开多个页面设置方法 IE11浏览器怎么设置一个窗口打开多个页面?一般新系统安装好了以后&#xff0c;默认的ie浏览器一个窗口都只能打开一个页面&#xff0c;一旦页面打开的多了的话&#xff0c;就会很卡&#xff0c;拖慢电脑的运行速度&#xff0c;而且整个…

php 如何模拟浏览器,利用php的curl扩展进行模拟浏览器访问网页

我们一般要抓取一个网站的静态页面来完成我们的需求&#xff0c;其实在这里面有很多种方式可以完成&#xff0c;php内置函数file_get_contents();file();readfile();都可以进行网页抓取&#xff0c;但是这种方式毕竟是有很大局限性的&#xff0c;例如我们要访问一个需要登录的网…

如何用极路由新插件【搜狐视频】进行远程下载

本文播放器家园网小编给大家分享如何用极路由新插件【搜狐视频】进行远程下载&#xff0c;如果大家在使用搜狐视频过程当中遇到类似问题&#xff0c;欢迎阅读本文!此外&#xff0c;在搜狐视频视频播放器上观看更流畅&#xff0c;画质更清晰&#xff0c;拒绝卡慢钝&#xff0c;而…

php数据库可转java数据库,php转java 系列2 Spring boo 链接数据库jdbc

php转java 系列2 Spring boo 链接数据库jdbcJDBC首先创建一个新项目&#xff0c;在创建项目时要注意导入依赖&#xff0c;在项目创建成功后就会看到在 pom.xml 文件中找到&#xff0c;但是如果在创建项目的时候没有导入&#xff0c;就要在pom.xml中手动的添加依赖&#xff1b;o…

edge浏览器下载位置设置在哪里设置

edge66760下载位置设置在哪里设置 edge浏览器下载位置设置在哪?很多Win10用户要求微软为Edge浏览器增加下载位置设置选项&#xff0c;那么win10 Edge浏览器的默认下载位置在哪里修改?怎么修改?在Windows10的反馈应用中&#xff0c;很多用户都反映Edge浏览器没有自定义下载位…

Python使用训练数据拟合模型

# 假设“满意度”是因变量&#xff0c;其他的是自变量 # 提取自变量&#xff08;特征&#xff09;和因变量&#xff08;目标&#xff09; X df_filtered_cleaned[[Bonus, Enhancement, Time_in_seconds]] y df_filtered_cleaned[Satisfaction] # 分割为训练集和测试集。 …

php连接excel表格数据类型,TP5 中使用PHPExcel 导出导入数据到excel表格

将下载好的PHPExcel文件夹放置在框架中的Vendor目录下&#xff0c;注意目录的结构&#xff0c;按照我的代码来基本上直接引用就能使用&#xff0c;如下图&#xff1a;导出数据代码如下//导出数据表 开始public function product(){$listdb(product)->select();vendor("…

PPTV网络电视如何修复浏览器支持异常

这篇文章主要说的是PPTV网络电视如何修复66760支持异常&#xff0c;希望可以帮助大家。pptv播放器是一款专注视频播放的客户端软件&#xff0c;免费下载安装&#xff0c;观看高清正版影视&#xff0c;可在线享受pptv播放器网站内全部免费高清正版视频&#xff0c;是最个性化、时…

oracle导致的负载高,Oracle 11g 数据库服务器CPU、IO负载高的故障排除流程

使用top查看负载高的进程~ [OSMSRDB]$ toptop - 11:02:43 up 12 days, 17:15, 4 users, load average: 1.50, 0.93, 0.36Tasks: 363 total, 1 running, 362 sleeping, 0 stopped, 0 zombieCpu(s): 1.2%us, 0.3%sy, 0.0%ni, 68.4%id,30.1%wa, 0.0%hi, 0.0%si, 0.0…

母狼高斯普和狐狸

《母狼高斯普和狐狸》母狼生了一只小狼&#xff0c;于是请来狐狸当教父。她说&#xff1a;“总之&#xff0c;狐狸是我们的近亲&#xff0c;见多识广而且头脑聪明;它能教好我儿子&#xff0c;帮他在世界上生存。” 狐狸装得很诚实地说&#xff1a;“亲爱的高司普太太&#xff…

oracle在线中文文档,Oracle TopLink

12.4.4. 事务管理将事务管理纳入到Service操作的执行中&#xff0c;你可以使用Spring通用的声明式的事务管理功能&#xff0c;参加下面的例子&#xff1a;xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…

优酷视频什么是登录保护?

登陆维护是对于移动终端(包括iphone、android、ipad等手机端)的账户维护作用。 打开了登陆维护以后&#xff0c;在一个新的机器设备上开展登陆(包含账户密码登陆、第三方授权登录等方法)时&#xff0c;必须根据验证码短信开展身份认证&#xff0c;验证通过后才可以登录成功&am…

PP视频怎么关闭PP视频虚拟键盘显示

今天小编给广大用户分享PP视频怎么关闭PP视频虚拟键盘显示。此外&#xff0c;在PP视频视频播放器上观看更流畅&#xff0c;画质更清晰&#xff0c;拒绝卡慢钝&#xff0c;而且还有许多自制独播综艺&#xff0c;让你看到停不下来!PP视频视频播放器是PP视频官方推出的一款网络视频…

清理linux 服务器的命令行,使用Linux上的Magic SysRq键修复冻结的X服务器,清理重新启动并运行其他低级命令 | MOS86...

在Linux中&#xff0c;魔术SysRq键可以直接发送命令到Linux内核。您可以使用它来恢复冻结或干净地重新启动系统&#xff0c;即使没有任何反应。魔术SysRq键是作为Linux键盘驱动程序的一部分实现的 - 只要Linux内核仍在运行&#xff0c;它将会工作。只有内核崩溃才能禁用此组合键…