打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
使用PHP读取和解析大文件实战

21CTO导读:在现在这篇文章中,我们将一起学习处理PHP中的大文件,避免因内存限制而无法使用的方法。


如果你想用PHP处理大文件,PHP提供了一些普通的PHP函数,比如file_get_contents()或file()函数,它们在处理超大文件时会存在一定局限性。


其中包括:


1.内存限制 


上面这些函数依赖于php.ini中memory_limit的参数值设置,可以调整增加这些值,但这些函数仍然不适合极大的文件,因为这些函数会把整个文件内容都读入到内存中。


如果文件的尺寸超过memory_limit的设置,这类文件都不会加载到内存中。现实中,比如我们有一个20G的的文件,想用PHP来处理,该怎么样处理?


2.不太好的用户体验


还有一个限制是生产环境的速度问题。如果我们把它输出到数组中,这样经常会出现在浏览器出现很长时间的等待,白页或者出错等情况。这样给用户的体验不太好。


对于这种技术限制,可以使用yield关键字来直接生成一个结果。


SplFileObject Class


在本文中,我们告诉大家使用PHP标准库中的SplFileObject类。


我们来演示,创建一个类来处理大文件。


这个类使用文件名做为输入参数。如下代码:


class BigFile

{

    protected $file;

 

    public function __construct($filename, $mode = 'r')

    {

        if (!file_exists($filename)) {

 

            throw new Exception('File not found');

        }

 

        $this->file = new SplFileObject($filename, $mode);

    }

 

}


接下来,我们定义一个遍历文件的方法,这个方法将使用fgets()函数一次读取文件一行。


我们也可以使用fread()函数的方法。


读取文本文件


fgets()适用于解析包含换行符的文本文件,而fread()适用于解析二进制文件。


该函数用于遍历文本文件的每一行内容。


protected function iterateText()

{

    $count = 0;

 

    while (!$this->file->eof()) {

 

        yield $this->file->fgets();

 

        $count++;

    }

    return $count;

}


读取二进制文件


来看另一个读取二进制的文件:


protected function iterateBinary($bytes)

{

    $count = 0;

 

    while (!$this->file->eof()) {

 

        yield $this->file->fread($bytes);

 

        $count++;

    }

}


直接读取


现在我们将定义一个采用迭代的类型,返回NoRewindIterator实例的方法。


我们使用NoRewindIterator强制单向读取。


public function iterate($type = 'Text', $bytes = NULL)

{

    if ($type == 'Text') {

 

        return new NoRewindIterator($this->iterateText());

 

    } else {

 

        return new NoRewindIterator($this->iterateBinary($bytes));

    }

 

}


整个类源文件如下如示:


class BigFile

{

    protected $file;

 

    public function __construct($filename, $mode = 'r')

    {

        if (!file_exists($filename)) {

 

            throw new Exception('File not found');

 

        }

 

        $this->file = new SplFileObject($filename, $mode);

    }

 

    protected function iterateText()

    {

        $count = 0;

 

        while (!$this->file->eof()) {

 

            yield $this->file->fgets();

 

            $count++;

        }

        return $count;

    }

 

    protected function iterateBinary($bytes)

    {

        $count = 0;

 

        while (!$this->file->eof()) {

 

            yield $this->file->fread($bytes);

 

            $count++;

        }

    }

 

    public function iterate($type = 'Text', $bytes = NULL)

    {

        if ($type == 'Text') {

 

            return new NoRewindIterator($this->iterateText());

 

        } else {

 

            return new NoRewindIterator($this->iterateBinary($bytes));

        }

 

    }

}


解析大文件:


我们对类文件做如下测试:


$largefile = new BigFile('file.csv');

 

$iterator = $largefile->iterate('Text'); // Text or Binary based on your file type

 

foreach ($iterator as $line) {

 

    echo $line;

 

}


现在这个类可以读取任何尺寸的大文件,没有任何限制,无限大。


我们可以在Laravel项目中,将该类添加到composer.json文件中自动加载该类并直接使用。


从此,我们可以轻松使用PHP解析和处理大尺寸文件了。


Happy PHP Coding!


作者:飞花逐月

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
PHP大文件读取操作
php使用http请求头实现文件下载
PHP文件下载代码
在PHP中判断文件是否被修改
PHP 文件写入或追加数据
用 PHP 内置函数 file_exists 检查文件或目录是否存在
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服