この記事では、主に PHP で大きなファイルを読み取るさまざまな方法を詳しく紹介します。興味のある方は参考にしてください。
大きなファイルを読むのはいつも悩みの種です。PHP を使用してさまざまな関数を直接使用して、小さなファイルを読み込むことができます。を実装しましたが、大きな記事に到達すると、一般的に使用されるメソッドが正常に使用できないか、時間がかかりすぎて行き詰まっていることがわかります。PHP で大きなファイルを読み取る際の問題の解決策を見てみましょう。この例が皆さんのお役に立てれば幸いです。約 500 万行を含む 800M のログ ファイルがあり、PHP を使用して最後の数行の内容を返します。
ファイル関数はすべての内容を一度にメモリに読み取るため、PHP は、一部の不適切に作成されたプログラムがメモリを占有しすぎてシステム メモリが不足することを防ぎます。サーバーがクラッシュするため、デフォルトでは最大メモリ使用量は 16M に制限されます。これは、php.ini のmemory_limit = 16M で設定されます。この値が -1 に設定されている場合、メモリ使用量は制限されません。
<?php ini_set('memory_limit', '-1'); $file = 'access.log'; $data = file($file); $line = $data[count($data) - 1]; echo $line; ?>コード全体の実行には 116.9613 (s) かかります。
私のマシンには 2G のメモリがあり、F5 キーを押して実行すると、システムがグレーになり、約 20 分後に回復します。このような大きなファイルをメモリに直接読み込むと、非常に深刻な結果になることがわかります。いいえ、必要ありません。memory_limit を高く設定しすぎることはできません。そうでない場合は、コンピュータ室に電話してマシンをリセットするように依頼するしかありません。
Linux コマンド ラインで、tail -n 10 access.log を直接使用して、ログ ファイルの最後の数行を簡単に表示できます。 PHP で tail コマンドを呼び出すには、次のように PHP コードを実行します。
<?php $file = 'access.log'; $file = escapeshellarg($file); // 对命令行参数进行安全转义 $line = `tail -n 1 $file`; echo $line; ?>コード全体の実行には 0.0034 (s) かかります 3。PHP の fseek を直接使用してファイル操作を実行します。この方法が最も一般的です。ファイルの内容はすべてポインタを介して直接読み込まれ、操作されるため、効率が非常に高くなります。 fseek を使用してファイルを操作する場合、さまざまな方法があり、効率は若干異なる場合があります。一般的に使用される 2 つの方法は次のとおりです:
方法 1
実装コードは以下の通りです
<?php $fp = fopen($file, "r"); $line = 10; $pos = -2; $t = " "; $data = ""; while ($line > 0) { while ($t != "\n") { fseek($fp, $pos, SEEK_END); $t = fgetc($fp); $pos--; } $t = " "; $data .= fgets($fp); $line--; } fclose($fp); echo $data ?>
コード全体の実行には0.0095(s)かかります
方法2
ファイルの末尾から読み取るためにfseekを引き続き使用しますが、今回は読み取っていません1 つずつではなく、部分ごとに読み取ります。データが読み取られるたびに、読み取られたデータは buf に配置され、改行文字 (\n) の数を使用して最後の $num 行が読み取られるかどうかが判断されます。データが読み取られました。実装コードは以下の通りです
<?php $fp = fopen($file, "r"); $num = 10; $chunk = 4096; $fs = sprintf("%u", filesize($file)); $max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file); for ($len = 0; $len < $max; $len += $chunk) { $seekSize = ($max - $len > $chunk) ? $chunk : $max - $len; fseek($fp, ($len + $seekSize) * -1, SEEK_END); $readData = fread($fp, $seekSize) . $readData; if (substr_count($readData, "\n") >= $num + 1) { preg_match("!(.*?\n){" . ($num) . "}$!", $readData, $match); $data = $match[0]; break; } } fclose($fp); echo $data; ?>
コード全体の実行には0.0009(s)かかります。
方法 3
<?php function tail($fp, $n, $base = 5) { assert($n > 0); $pos = $n + 1; $lines = array(); while (count($lines) <= $n) { try { fseek($fp, -$pos, SEEK_END); } catch (Exception $e) { fseek(0); break; } $pos *= $base; while (!feof($fp)) { array_unshift($lines, fgets($fp)); } } return array_slice($lines, 0, $n); } var_dump(tail(fopen("access.log", "r+"), 10)); ?>
コード全体の実行には 0.0003(s) かかります。
方法 4、PHP の stream_get_line 関数は、500,000 データ時間の大きなファイルを読み取るのに約 20 秒かかります。サンプルコードは以下の通りです
$fp = fopen('./iis.log', 'r'); //文件 while (!feof($fp)) { //for($j=1;$j<=1000;$j++) { //读取下面的1000行并存储到数组中 $logarray[] = stream_get_line($fp, 65535, "\n"); // break; // } }
概要: 上記がこの記事の全内容です。皆さんの学習に役立つことを願っています。
関連する推奨事項:
PHPのクラスの継承と使用例の詳細な説明PHPがデータページング表示機能を実装する方法phpWebサイトのルートの物理パスを取得するいくつかの方法ディレクトリ
以上がPHP で大きなファイルを読み取るためのさまざまな方法の詳細な説明と例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。