首先,我不是在寻找一个回答说"检查你的PHP内存限制"或"你需要添加更多的内存"或这些东西…我在一台专用的机器上,有8GB的ram;512MB是内存限制。我总是在一行上得到内存不足的错误:
澄清一下:这部分代码属于Joomla!CMS .
function get($id, $group, $checkTime){
$data = false;
$path = $this->_getFilePath($id, $group);
$this->_setExpire($id, $group);
if (file_exists($path)) {
$data = file_get_contents($path);
if($data) {
// Remove the initial die() statement
$data = preg_replace('/^.*'n/', '', $data); // Out of memory here
}
}
return $data;
}
这是Joomla缓存的一部分…这个函数读取缓存文件,并删除第一行阻止对文件的直接访问,并返回其余的数据。
可以看到,该行使用preg_replace来删除缓存文件中的第一行,它总是:
<?php die("Access Denied"); ?>
我的问题是,在我看来,作为一个简单的过程(从文件内容中删除第一行),如果初始$data很大,它会消耗大量内存吗?如果是这样,解决这个问题的最佳方法是什么?我不介意缓存文件没有die()行,我可以采取安全措施并阻止对缓存文件的直接访问。
我错了吗?
正如帖子所建议的那样,regex似乎创造了更多的问题而不是解决它们。我试过:
echo memory_get_usage() . "'n";
在正则表达式之后,然后使用substr()
尝试相同的语句。在内存使用方面差别很小。几乎没有。
感谢你的贡献,我仍在努力找出发生这种情况的原因。
使用substr避免占用大量内存的preg_replace()
,如下所示:
$data = substr($data, strpos($data, '?>') + 3);
作为一般建议,如果您可以使用其他字符串/数组函数来完成相同的任务,则不要使用正则表达式,因为正则表达式函数比核心字符串/数组函数更慢且消耗更多内存。
这在PHP文档中也有明确的警告,参见一些例子:
http://www.php.net/manual/en/function.preg-match.php refsect1-function.preg-match-noteshttp://www.php.net/manual/en/function.preg-split.php refsect1-function.preg-split-notes
不要使用字符串函数来替换大字符串中的内容。您可以循环遍历文件的行,并在找到所需内容后中断。查看PHP文档:
http://php.net/manual/en/function.fgets.php基本上就是@ buckley刚才说的:p
如果您只想删除文件的第一行并返回其余部分,您应该使用file
:
$lines = file($path);
array_shift($lines);
$data = implode("'n", $lines);
不要使用一次性获取整个文件的file_get_contents()
,因为它太大而无法在上面运行regexp,您应该将fopen()
与fgets()
结合使用(http://php.net/fgets)。这个函数逐行获取文件。
然后可以选择在特定行上执行regexp。或者直接跳过整行。
所以不用:
$data = file_get_contents($path);
if($data) {
// Remove the initial die() statement
$data = preg_replace('/^.*'n/', '', $data); // Out of memory here
}
试试这个:
$fileHandler = fopen($path,'r');
$lineNumber = 0;
while (($line = fgets($fileHandler)) !== false) {
if($lineNumber++ != 0) { // Skip the initial die() statement
$data .= $line; // or maybe echo out $line directly so $data doesn't take up too much memory as well.
}
}
我建议你在文件中使用这个,包括缓存的文件:
define('INCLUDESALLOW', 1);
和将包含的文件:
if( !defined('INCLUDESALLOW') ) die("Access Denied");
那就用include
代替file_get_contents
。这将在包含的PHP代码中运行,但不能100%确定这是否是您需要的。
有时会使用比php分配的8 MB更多的内存。如果无法通过提高代码效率来使用更少的内存,则可能必须增加可用内存。这可以通过两种方式实现。
限制可以在php.ini中设置为全局默认值:
memory_limit = 32M
或者你可以在脚本中重写它,像这样:
<?php
ini_set('memory_limit', '64M');
...
有关PHP内存限制的更多信息,请参见This SO问题或ini.memory-limit.