PHP csv大文件读取与操作

本文介绍了在PHP中处理大文件,特别是CSV文件时,如何避免内存溢出问题。通过对比传统的file_get_contents()和fgetcsv(),推荐使用SplFileObject类来逐行读取和操作文件。该类提供了更高效的解决方案,如计算文件总行数。文中给出了具体的代码示例,展示了SplFileObject在处理大文件时的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多时候,要处理文件,一般最先想到的就是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);
由于数据有点长,只贴以下部分图片:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值