诸多大互联网公司的面试都会有这么个问题,有个4G的文件,如何用只有1G内存的机器去计算文件中出现次数最多的数字(假设1行是1个数组,例如QQ号 码)。如果这个文件只有4B或者几十兆,那么最简单的办法就是直接读取这个文件后进行分析统计。但是这个是4G的文件,当然也可能是几十G甚至几百G的文 件,这就不是直接读取能解决了的。

同样对于如此大的文件,单纯用PHP做是肯定行不通的,我的思路是不管多大文件,首先要切割为多个应用可以承受的小文件,然后批量或者依次分析统计小文件后再把总的结果汇总后统计出符合要求的最终结果。类似于比较流行的MapReduce模型,其核心思想就是“Map(映射)”和“Reduce(化简)”,加上分布式的文件处理,当然我能理解和使用到的只有Reduce后去处理。

假设有1个10亿行的文件,每行一个6位-10位不等的QQ号码,那么我需要解决的就是计算在这10亿个QQ号码中,重复最多的前10个号码,使用下面的PHP脚本生成这个文件,很可能这个随机数中不会出现重复,但是我们假设这里面会有重复的数字出现。

$fp = fopen('qq.txt','w+');
for( $i=0; $i<1000000000; $i++ ){
$str = mt_rand(10000,9999999999)."\n";
fwrite($fp,$str);
}
fclose($fp);

生成文件的世界比较长,Linux下直接使用php-client运行PHP文件会比较节省时间,当然也可以使用其他方式生成文件。生成的文件大约11G。

然后使用Linux Split切割文件,切割标准为每100万行数据1个文件。

split -l 1000000 -a 3 qq.txt qqfile

qq.txt被分割为名字是qqfileaaa到qqfilebml的1000个文件,每个文件11mb大小,这时再使用任何处理方法都会比较简单了。我还是使用PHP进行分析统计:

$results = array();
foreach( glob('/tmp/qq/*') as $file ){
$fp = fopen($file,'r');
$arr = array();
while( $qq = fgets($fp) ){
$qq = trim($qq);
isset($arr[$qq]) ? $arr[$qq]++ : $arr[$qq]=1;
}
arsort($arr);
//以下处理方式存在问题
do{
$i=0;
foreach( $arr as $qq=>$times ){
if( $i > 10 ){
isset($results[$qq]) ? $results[$qq]+=$times : $results[$qq]=$times;
$i++;
} else {
break;
}
}
} while(false);
fclose($fp);
}
if( $results ){
arsort($results);
do{
$i=0;
foreach( $results as $qq=>$times ){
if( $i > 10 ){
echo $qq . "\t" . $times . "\n";
$i++;
} else {
break;
}
}
} while(false);
}

这样每个样本取前10个,最后放到一起分析统计,不排除有个数在每个样本中都排名第11位但是总数绝对在前10的可能性,所以后面统计计算算法还需要改进。

也许有人说使用Linux中的awk和sort命令可以完成排序,但是我试了下如果是小文件还可以实现,但是11G的文件,不管是内存还是时间都无法承受。下面是我改的1个awk+sort的脚本,或许是写法有问题,求牛人指导。

awk -F '\\@' '{name[$1]++ } END {for (count in name) print name[count],count}' qq.txt |sort -n > 123.txt

awk -F '\\@' '{name[$1]++ } END {for (count in name) print name[count],count}' qq.txt |sort -n > 123.txt

出处:http://www.feiyan.info/50.html

PHP几个几十个G大文件数据统计并且排序处理的更多相关文章

  1. Java内存映射,上G大文件轻松处理

    内存映射文件(Memory-mapped File),指的是将一段虚拟内存逐字节映射于一个文件,使得应用程序处理文件如同访问主内存(但在真正使用到这些数据前却不会消耗物理内存,也不会有读写磁盘的操作) ...

  2. Java NIO内存映射---上G大文件处理(转)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果 ...

  3. C#windows桌面应用小程序制作——大文件数据分段解析存储

    现在的任务就是做一个大文件解析的桌面应用小程序,具体需求就是:将一个很大的文件里的数据按一定标志拆分然后分别保存到某个文件夹下面. 解析的文件内容为以下内容: windows 应用小程序界面 具体代码 ...

  4. Sybase IQ如何将大文件数据迅速加载到数据库

    试想一下,如果一个文件5G.10G甚至更大.如何将它迅速地加载到数据库指定的表呢?我们看看Sybase IQ是如何迅速地将表的数据加载到数据库的. 数据文件格式: 1440,2011-01-09 00 ...

  5. 用php导入10W条+ 级别的csv大文件数据到mysql。导出10W+级别数据到csv文件

    转自:http://blog.csdn.net/think2me/article/details/12999907 1. 说说csv 和 Excel 这两者都是我们平时导出或者导入数据一般用到的载体. ...

  6. PHP实现CSV大文件数据导入到MYSQL数据库

    <?php $db_host="192.168.1.10"; $db_user="root"; $db_psw="11111"; $d ...

  7. rsync增量传输大文件优化技巧

    问题 rsync用来同步数据非常的好用,特别是增量同步.但是有一种情况如果不增加特定的参数就不是很好用了.比如你要同步多个几十个G的文件,然后网络突然断开了一下,这时候你重新启动增量同步.但是发现等了 ...

  8. 【.Net】 大文件可使用的文本分组统计工具(附带源码,原创)

    本工具可实现的效果: 1.读取大文件(大于1GB) 2.根据分隔符分割后的列分组 3.速度快. 4.处理过程中,可以随时停止处理,操作不卡死. 5.有对当前内存的实时监测,避免过多占用内存,影响系统运 ...

  9. python 下载大文件

    当使用requests的get下载大文件/数据时,建议使用使用stream模式. 当把get函数的stream参数设置成False时,它会立即开始下载文件并放到内存中,如果文件过大,有可能导致内存不足 ...

随机推荐

  1. [译]如何使用 Docker 组件开发 Django 项目?

    原文地址:Django Development With Docker Compose and Machine 以下为译文 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包 ...

  2. ios开发与安卓开源项目及库

    自己总结的iOS.mac开源项目及库 https://github.com/Tim9Liu9/TimLiu-iOS 自己总结的Android开源项目及库 https://github.com/Tim9 ...

  3. sftp的安装和使用

    http://blog.srmklive.com/2013/04/24/how-to-setup-sftp-server-ftp-over-ssh-in-ubuntu/ In my previous ...

  4. RxJava+Retrofit+MVP构建的App——聚合资讯

    RtfRxMVP 聚合资讯APP,提供热点资讯,天气预报以及笑话精选服务,使用 Retrofit + RxJava + MVP 构建代码. Hello U 这是我的一个练习项目,第一次尝试运用 MVP ...

  5. Dreamweaver修改页面编码

    想修改当前页面编码,可以选择菜单 :修改->页面属性->标题/编码 想设置新建页面默认编码,可以选择菜单: 编辑->首选参数->新建文档 的默认编码里面修改

  6. MyBatis学习总结_17_Mybatis分页插件PageHelper

    如果你也在用Mybatis,建议尝试该分页插件,这一定是最方便使用的分页插件. 分页插件支持任何复杂的单表.多表分页,部分特殊情况请看重要提示. 想要使用分页插件?请看如何使用分页插件. 物理分页 该 ...

  7. Wordnet 与 Hownet 比较

    近年来,随着计算机本身以及信息高速公路的飞速发展,人们开始更加重视语义的研究.各国都致力于可用于自然语言处理的大规模语义词典或大规模知识库的建设.例如:普林斯顿大学的英语Wordnet,微软的Mind ...

  8. Spring AOP 创建切面

        增强被织入到目标类的所有方法中,但是如果需要有选择性的织入到目标类某些特定的方法中时,就需要使用切点进行目标连接点的定位.增强提供了连接点方位信息:如织入到方法前面.后面等,而切点进一步描述织 ...

  9. LINUX下的MYSQL默认表名区分大小写

    让MYSQL不区分表名大小写的方法其实很简单: 1.用ROOT登录,修改/etc/my.cnf,该文件的路径也可能是/usr/my.cnf. 2.加入一行:lower_case_table_names ...

  10. nginx添加nginx_mod_h264_streaming-2.2.7模块编译报错

    报错ngx_http_streaming_module.c:158: 错误:‘ngx_http_request_t’ 没有名为 ‘zero_in_uri’ 的成员.这需要修改nginx_mod_h26 ...