PHP csv大文件读取与操作

来源:互联网 发布:阿里云域名过户流程 编辑:程序博客网 时间:2024/06/17 22:22

很多时候,要处理文件,一般最先想到的就是file_get_contents() 等函数,但是在文件比较大的情况下,盲目的使用这样的函数会造成PHP的内存溢出(不使用任何参数)等致命错误。

当然,有一些函数能够一行一行的读取数据,比如fread(),fgetcsv(),而事实上,一般操作csv文件也是使用这几个函数,在正常使用过程中,只要没有特殊的需求,还是可以胜任大多数的情况。比如,如果有一个2000w~5000w条数据的文件,只想获取文件的总行数怎么办,循环累加吗?这显然是最直接的方法,其实还有更好的方法。

在PHP5以后,PHP为文件提供了一个面向对象接口类:SplFileObject。

详情可以查看:

The SplFileObject class

http://www.php.net/manual/zh/class.splfileobject.php

这里提供一段简单有趣的程序。

function useSplFileObject($csvfile) {    $splFileObject = new SplFileObject($csvfile, 'rb');    $splFileObject->seek(filesize($csvfile));    $num =  $splFileObject->key();    return $num;}$data = useSplFileObject('test.csv');var_dump($data);

贴个对比的(循环累加):

$header = fopen('test.csv','r');$i = 0;while( !feof($header) ){    fgetcsv($header);    $i++;}var_dump($i);

系统命令行直接获取:


通过上面可以看出,单纯获取文件的行数,这种需求,使用PHP提供的SplFileObject类是比较好的选择。

贴一个拓展的(offset):

function useSplFileObject($csvfile,$offset,$len) {    $splFileObject = new SplFileObject($csvfile, 'rb');    $splFileObject->seek(filesize($csvfile));    $splFileObject->seek($offset);    while ((!($splFileObject->eof()) && $len)){        $content[]=$splFileObject->current();        $splFileObject->next();        $len--;    }    return $content;}$data = useSplFileObject('test.csv',12000000,10);var_dump($data);
以上测试test.csv输出从12000000行起,10行的内容。



这是一个不错的体验,尤其是大文件获取,不方便调程序的执行时间和内存的情况下。

当然,原生的fgetcsv,也是可以的。上面的程序相应修改如下:

function csv_get_offsetlines($csvfile, $lines, $offset = 0) {    if(!$fp = fopen($csvfile, 'r')) {        return false;    }    $offset = $offset - 1;    $i = $j = 0;    while (false !== ($line = fgets($fp))) {        if($i++ < $offset) {            continue;        }        break;    }    $data = array();    while(($j++ < $lines) && !feof($fp)) {        $data[] = fgetcsv($fp);    }    fclose($fp);    return $data;}$data = csv_get_offsetlines('test.csv', 10, 12000000);var_dump($data);
由于数据有点长,只贴以下部分图片: