PHPで大きなファイルの特定の行を読み取る方法

藏色散人
リリース: 2023-03-13 20:30:01
オリジナル
2065 人が閲覧しました

大きなファイルの特定の行を読み取るために PHP を実装する方法: 1. ファイル関数を直接使用して操作します; 2. Linux tail コマンドを呼び出して最後の数行を表示します; 3. PHP の fseek を使用して実行しますファイル操作; 4. PHP の stream_get_line 関数による読み取り。

PHPで大きなファイルの特定の行を読み取る方法

#この記事の動作環境:Windows7 システム、PHP7.1 バージョン、DELL G3 パソコン

php 読み方大きなファイルの行?

PHP で大きなファイルを読み取るさまざまな方法の紹介

大きなファイルの読み取りは常に頭痛の種でした。PHP 開発を使用すると、さまざまな方法で小さなファイルを読み取ることができます。関数の実装、しかし、大きな記事に到達すると、一般的に使用されるメソッドが正常に使用できないか、時間がかかりすぎて行き詰まっていることがわかります。PHP で大きなファイルを読み取る際の問題の解決策を見てみましょう。例が役に立ちます。

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

要件:

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

実装方法:

1. file関数を直接使って操作する

file関数は内容を一度にメモリ上に読み込むため、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 (秒) かかります。

私のマシンには 2 G のメモリが搭載されています。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 を見つけてから、最後の行の開始位置を見つけて、この行のデータを取得し、次の行の開始位置を見つけて、この行の位置を取得するというように、$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 (秒)かかります

方法 2

それでも fseek を使用して最後から読み取りますファイルのデータを読み込みますが、今回は少しずつ読み取るのではなく、少しずつ読み取ります。データが読み取られるたびに、読み取られたデータは 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(秒)かかります。

方法 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で大きなファイルの特定の行を読み取る方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
php
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート