[解決済み] PHP を使ってファイルの最終行を読み取るための最良の方法は何ですか?
質問
私のPHPアプリケーションでは、次のことが必要です。
の末尾から始まる複数の行を読み取る必要があります。
多くのファイル
(主にログ)。最後の1行だけが必要なこともあれば、数十行、数百行が必要なこともあります。
数十または数百を必要とします。基本的に、私はUnixの
tail
コマンドのように柔軟なものが欲しいのです。
ここでは、ファイルから最後の1行を取得する方法についての質問があります(しかし 必要なのは N 行が必要です)、そして異なった解決策が与えられました。どれがベストで、どれがより良いパフォーマンスなのか、よくわかりません。 がベストで、どちらがより良いパフォーマンスなのかわかりません。
どのように解決するのですか?
メソッドの概要
インターネットで検索していると、さまざまなソリューションに出会います。私はそれらを次の 3 つのアプローチにまとめることができます。 3つのアプローチに分類できます。
-
素朴
を使用するもの
file()
PHPの関数です。 -
不正行為
走っているもの
tail
コマンドを実行するもの。 -
強大な
を使って、開いたファイルの中を嬉々として飛び回るもの。
fseek()
.
結局、5つの解決策を選んだ(書いた)のですが、そのうちの1つは 素朴な というもの、そして インチキ 一つ と3つの 強大 のものです。
- 最も簡潔な 素朴な 解決策 , 組み込みの配列関数を使用して。
-
は
に基づく唯一の可能な解決策は
tail
コマンド がありますが、これには は少し大きな問題があります。tail
が利用できない場合、つまり 非Unix(Windows)やシステム関数を許可しない制限された環境など、が利用できない場合は実行されません。 関数を許可しない制限された環境などです。 - での解決策は シングルバイト を検索して、ファイルの終わりから読み込まれます。 を検索し、改行文字をカウントすることで はここで .
- は マルチバイトバッファード のソリューションは、大きなファイルのために最適化され、見つかった ここで .
- 若干の 解決策4の修正版 この場合、バッファの長さは であり、取得する行数に応じて決定されます。
すべてのソリューション 作業 . どのようなファイルでも、どのような行数でも、期待通りの結果を返すという意味では どのようなファイルでも、どのような行数でも、期待通りの結果を返すという意味で (ただし、#1 の解決策は、ファイルが大きい場合に PHP のメモリ制限にひっかかる可能性があり は、大きなファイルの場合に PHP のメモリ制限を破って何も返さない可能性があります)。しかし、どれが が良いのでしょうか?
パフォーマンステスト
質問に答えるために、私はテストを実行します。こういうのはそういうものでしょう?
サンプルを用意しました。
100KBのファイル
で見つけた異なるファイルを結合して
私の
/var/log
ディレクトリにある異なるファイルを結合しています。それから、5つの解決策のそれぞれを使用するPHPスクリプトを書きました。
を取得する PHP スクリプトを作成しました。
1, 2, .., 10, 20, ... 100, 200, ..., 1000
行
をファイルの末尾から順に実行します。それぞれのテストは10回繰り返されます(これは
のようなものです。
5 × 28 × 10 = 1400
のように)、測定します。
平均経過時間
時間
をマイクロ秒単位で測定します。
私のローカルの開発マシン (Xubuntu 12.04, PHP 5.3.10, 2.70 GHz dual core CPU, 2 GB RAM) で PHP コマンドライン インタープリターを使用してスクリプトを実行しました。 インタプリタを使って実行しました。以下はその結果です。
解決策#1と#2は、より悪いもののようです。3は、数行を読む必要がある場合のみ有効です。 数行を読む必要があるときだけです。 解決策#4と#5は最も良いもののように思われる。 動的バッファサイズによってアルゴリズムがどのように最適化されるかに注目。 実行時間は、バッファが減少しているため、数行で少し小さくなります。
より大きなファイルで試してみましょう。もし私たちが 10 MB のログファイルを読まなければならないとしたらどうでしょう?
さて、解決策その 1 は圧倒的に悪いものです:実際、10 MB のファイル全体をメモリにロードすることは をメモリに読み込むことは、良いアイデアではありません。私は 1MB と 100MB のファイルでもテストを実行しました。 実質的に同じ状況です。
小さなログファイルの場合は?のグラフです。 10 KB ファイルのグラフです。
解決策その1は、今一番良い方法です! 10KBをメモリにロードすることは、PHPにとって大きな問題ではありません。 PHPにとって大きな問題ではありません。また、#4 と#5 も良いパフォーマンスです。しかし、これはエッジケースです:10KBのログは は、150/200 行を意味する...
<ブロッククオート私のテストファイル、ソース、結果をすべてダウンロードすることができます。 ここで .
最終的な感想
ソリューション#5 は、一般的な使用例として強く推奨されます。 どのようなファイル サイズでもうまく機能し、数行を読み取るときに特に優れたパフォーマンスを発揮します。
避けるべきは 解決策その1 もし は、10KB以上のファイルを読み込む必要があります。
解決方法 #2 そして #3 は、私が実行する各テストで最適なものではありません。#2 は 2ms 以下で実行されることはありません。 2は2ms以下で実行されることはなく、#3は質問した行数に大きく影響されます。 の行数に大きく影響されます(1、2行でかなりうまくいきます)。
関連
-
[解決済み】PHP - 構文エラー、予期しないT_CONSTANT_ECAPSED_STRING [閉店].
-
[解決済み】stdClassクラスのオブジェクトが文字列に変換されない。
-
[解決済み] Uncaught SyntaxError: JSON の位置 1 に予期しないトークン o があります。
-
[解決済み] オートロードとは何ですか; spl_autoload、__autoload、spl_autoload_register はどのように使うのですか?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] PHPの文字列で、シングルクオートとダブルクオートの違いは何ですか?
-
[解決済み] SQL Serverで結果をページ分割する最も良い方法は何ですか?
-
[解決済み】PHPで配列やデータをソートするにはどうすればいいですか?
-
[解決済み】FlashゲームのPHPベースのハイスコアテーブルをハッキングされないようにする最善の方法は何でしょうか?
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Notice: 非オブジェクトのプロパティを取得しようとしているエラー
-
[解決済み】XAMPPポート80をPID 4の「Unable to open process」が使用中 [重複] XAMPPポート80をPID 4の「Unable to open process」が使用中。]
-
[解決済み】「セッションキャッシュリミッターを送信できません - ヘッダーはすでに送信されています」【重複】。
-
[解決済み】変な電話番号を生成するフェイカー?
-
[解決済み】新しいPHPMailerはPHPMailerAutoload.phpが必要?
-
[解決済み】stdClassクラスのオブジェクトが文字列に変換されない。
-
[解決済み】子テーマのCSSが親テーマをオーバーライドしない
-
[解決済み】警告: file_get_contents(): https:// ラッパーがサーバー構成ですべて無効になっています。
-
[解決済み】phpのシンタックスエラー、予期しないT_IFエラーを修正する方法は?[クローズド]。
-
[解決済み] Forbidden :このサーバーの /phpmyadmin にアクセスする権限がありません。