ホームページ  >  記事  >  バックエンド開発  >  PHP で大きなファイルを読み取るためのさまざまな方法の詳細な説明と例

PHP で大きなファイルを読み取るためのさまざまな方法の詳細な説明と例

墨辰丷
墨辰丷オリジナル
2018-06-04 10:20:091670ブラウズ

この記事では、主に PHP で大きなファイルを読み取るさまざまな方法を詳しく紹介します。興味のある方は参考にしてください。

大きなファイルを読むのはいつも悩みの種です。PHP を使用してさまざまな関数を直接使用して、小さなファイルを読み込むことができます。を実装しましたが、大きな記事に到達すると、一般的に使用されるメソッドが正常に使用できないか、時間がかかりすぎて行き詰まっていることがわかります。PHP で大きなファイルを読み取る際の問題の解決策を見てみましょう。この例が皆さんのお役に立てれば幸いです。


PHP では、ファイルを読み取るときに、file や file_get_contents などの関数を使用するのが最も簡単な方法で、数行の簡単なコードで必要な関数を美しく完成させることができます。ただし、操作するファイルが比較的大きなファイルの場合、これらの機能では不十分な場合があります。ここでは、大きなファイルを読み取るための一般的な操作方法について説明します。

要件:

約 500 万行を含む 800M のログ ファイルがあり、PHP を使用して最後の数行の内容を返します。

実装方法:

1. ファイル関数を直接使用して操作します

ファイル関数はすべての内容を一度にメモリに読み取るため、PHP は、一部の不適切に作成されたプログラムがメモリを占有しすぎてシステム メモリが不足することを防ぎます。サーバーがクラッシュするため、デフォルトでは最大メモリ使用量は 16M に制限されます。これは、php.ini のmemory_limit = 16M で設定されます。この値が -1 に設定されている場合、メモリ使用量は制限されません。

次は、 file を使用してこのファイルの最後の行を抽出するコードです:

<?php
  ini_set(&#39;memory_limit&#39;, &#39;-1&#39;);
  $file = &#39;access.log&#39;;
  $data = file($file);
  $line = $data[count($data) - 1];
  echo $line;
?>

コード全体の実行には 116.9613 (s) かかります。

私のマシンには 2G のメモリがあり、F5 キーを押して実行すると、システムがグレーになり、約 20 分後に回復します。このような大きなファイルをメモリに直接読み込むと、非常に深刻な結果になることがわかります。いいえ、必要ありません。memory_limit を高く設定しすぎることはできません。そうでない場合は、コンピュータ室に電話してマシンをリセットするように依頼するしかありません。

2. Linux tail コマンドを直接呼び出して、最後の数行を表示します

Linux コマンド ラインで、tail -n 10 access.log を直接使用して、ログ ファイルの最後の数行を簡単に表示できます。 PHP で tail コマンドを呼び出すには、次のように PHP コードを実行します。

<?php
  $file = &#39;access.log&#39;;
  $file = escapeshellarg($file); // 对命令行参数进行安全转义
  $line = `tail -n 1 $file`;
  echo $line;
?>

コード全体の実行には 0.0034 (s) かかります

3。PHP の fseek を直接使用してファイル操作を実行します。この方法が最も一般的です。ファイルの内容はすべてポインタを介して直接読み込まれ、操作されるため、効率が非常に高くなります。 fseek を使用してファイルを操作する場合、さまざまな方法があり、効率は若干異なる場合があります。一般的に使用される 2 つの方法は次のとおりです:


方法 1

最初に fseek でファイルの最後の EOF を検索し、次に先頭の EOF を検索します。最後の行の位置を確認し、この行のデータを取得し、次の行の開始位置を見つけて、この行の位置を取得するというように、$num 行が見つかるまで続きます。

実装コードは以下の通りです

<?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(&#39;./iis.log&#39;, &#39;r&#39;); //文件 
while (!feof($fp)) { 
 //for($j=1;$j<=1000;$j++) {     //读取下面的1000行并存储到数组中 
 $logarray[] = stream_get_line($fp, 65535, "\n"); 
    // break;
 // } 
 
 }

概要: 上記がこの記事の全内容です。皆さんの学習に役立つことを願っています。

関連する推奨事項:

PHPのクラスの継承と使用例の詳細な説明


PHPがデータページング表示機能を実装する方法


phpWebサイトのルートの物理パスを取得するいくつかの方法ディレクトリ

以上がPHP で大きなファイルを読み取るためのさまざまな方法の詳細な説明と例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。