4

まず第一に、「PHP のメモリ制限を確認してください」または「メモリを追加する必要があります」などの回答を探しているわけではありません。そのうちの 512MB がメモリ制限です。私は常に1行でメモリ不足エラーを受け取ります:

明確にするために:コードのこの部分は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() 行がなくても、キャッシュ ファイルが存在することは問題ありません。

私が間違っている?

アップデート

投稿で示唆されているように、正規表現は解決するよりも多くの問題を生み出すようです。私はもう試した:

echo memory_get_usage() . "\n";

正規表現の後、 を使用して同じステートメントを試しましたsubstr()。メモリ使用量の違いはごくわずかです。ほとんど何もありません。

それはあなたの貢献のためです、私はまだなぜこれが起こるのかを見つけようとしています.

4

6 に答える 6

5

次のように substr を使用して、メモリ ハングリーを回避しますpreg_replace()

$data = substr($data, strpos($data, '?>') + 3);

一般的なアドバイスとして、他の文字列/配列関数を使用して同じタスクを実行できる場合は、正規表現を使用しないでください。正規表現関数はコアの文字列/配列関数よりも遅く、より多くのメモリを消費します。

これは、PHP ドキュメントでも明示的に警告されています。いくつかの例を参照してください。

http://www.php.net/manual/en/function.preg-match.php#refsect1-function.preg-match-notes http://www.php.net/manual/en/function.preg-split .php#refsect1-function.preg-split-notes

于 2013-04-17T12:26:43.367 に答える
3

巨大な文字列内の何かを置き換えるために文字列関数を使用しないでください。ファイルの行を循環して、探しているものが見つかったら中断することができます。ここでPHPドキュメントを確認してください:

http://php.net/manual/en/function.fgets.php

基本的に@cbuckleyが言ったこと:p

于 2013-04-17T12:25:11.800 に答える
1

ファイルの最初の行を削除して残りを返したい場合は、次を使用する必要がありますfile

$lines = file($path);
array_shift($lines);
$data = implode("\n", $lines);
于 2013-04-17T12:26:09.360 に答える
1

正規file_get_contents()表現を実行するには大きすぎる可能性があるファイル全体を一度に取得するのではなく、( http://php.net/fgetsfopen() )と組み合わせて使用​​する必要があります。この関数は、ファイルを 1 行ずつ取得します。fgets()

次に、特定の行で正規表現を実行することを選択できます。または、あなたの場合、行全体をスキップしてください。

したがって、代わりに:

$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.
    }
}
于 2013-04-21T07:49:05.013 に答える
0

キャッシュされたファイルを含むファイルでこれを使用することをお勧めします。

define('INCLUDESALLOW', 1);

含まれるファイルには次のように書かれています。

if( !defined('INCLUDESALLOW') ) die("Access Denied");

次に、includeの代わりに使用しfile_get_contentsます。ただし、これは含まれている PHP コードを実行しますが、それが必要かどうかは 100% わかりません。

于 2013-04-17T12:25:59.133 に答える