中福在线源码搭建与PHP读取和解析大文件实战

如果你想用PHP处理大文件,PHP提供了一些普通的PHP函数,比如file_get_contents()或file()函数,它们在处理超大文件时会存在一定局限性。中福在线源码搭建QQ:2152876294 网址diguaym.com

 

其中包括:

 

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;
}


读取二进制文件

 

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

function DisplayWindowSize(){

  var w=window.innerWidth
  || document.documentElement.clientWidth
  || document.body.clientWidth;
}


直接读取

 

现在我们将定义一个采用迭代的类型,返回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文件中自动加载该类并直接使用。

转载于:https://my.oschina.net/u/3936807/blog/1921939

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值