方法が何通りあるか数えてみましょう
PHP のような最新のプログラミング言語を使用する楽しみの 1 つは、利用可能なオプションが膨大にあることです。特にファイル処理に関しては、PHP は Perl のモットーである「方法は複数ある」を簡単に勝ち取ります。しかし、非常に多くのオプションが利用可能であるため、その作業に最適なツールはどれでしょうか?もちろん、実際の答えはファイル解析の目的によって異なるため、時間をかけてすべてのオプションを検討する価値があります。
トップに戻る
従来の fopen メソッド
fopen メソッドは、元の C および C プログラマにとっておそらく最もよく知られているものです。これらの言語を使用したことがあれば、多かれ少なかれ馴染みのあるツールだからです。何年もの間。これらの方法のいずれでも、リスト 1 に示すように、ファイルは fopen (データの読み取りに使用される関数) を使用する標準的な方法で開かれ、その後 fclose を使用して閉じられます。
リスト 1. fgets を使用してファイルを開いて読み取る
$file_handle = fopen("myfile", "r");
while (!feof($file_handle)) {
$line = fgets ( $file_handle);
echo $line;
}
fclose($file_handle)
長年のプログラミング経験を持つほとんどのプログラマーはこれらの関数について詳しく説明します。次の手順を効果的に実行します:
ファイルを開きます。 $file_handle には、ファイル自体への参照が保存されます。
ファイルの最後に到達したかどうかを確認してください。
ファイルの終わりに達するまでファイルの読み取りを続け、読み取られた各行を出力します。
ファイルを閉じます。
これらの手順を念頭に置いて、ここで使用される各ファイル関数を確認していきます。
fopen
fopen 関数はファイルへの接続を作成します。 「接続を作成する」と言ったのは、fopen はファイルを開くだけでなく、URL も開くことができるためです。 $fh = fopen("http://127.0.0.1/", "r"); この行のコードは次のとおりです。上記のページへの接続が作成され、ローカル ファイルのように読み取りを開始できるようになります。
注: fopen で使用される「r」は、ファイルが読み取り専用で開かれることを示します。ファイルへのデータの書き込みはこの記事の範囲外であるため、その他のオプションはすべてリストしません。ただし、クロスプラットフォーム互換性のためにバイナリ ファイルから読み取る場合は、「r」を「rb」に変更する必要があります。この例については後で説明します。
feof
feof コマンドは、ファイルの終わりに到達したかどうかを検出し、True または False を返します。リスト 1 のループは、ファイル「myfile」の終わりに到達するまで続きます。注: URL の読み取り中に、読み取るデータがなくなってソケットがタイムアウトした場合にも、feof は False を返します。
fclose
リスト 1 の最後までスキップすると、fclose は fopen の逆の動作を行い、ファイルまたは URL への接続を閉じます。この関数を実行すると、ファイルまたはソケットから情報を読み取ることができなくなります。
fgets
リスト 1 の数行戻ると、ファイル処理の核心、つまり実際にファイルを読み取る作業に移ります。 fgets 関数は、最初の例で使用する武器です。ファイルからデータ行を抽出し、文字列として返します。その後、データを印刷したり、その他の方法で操作したりできます。リスト 1 の例では、ファイル全体が正常に出力されます。
処理されるデータのチャンクのサイズを制限する場合は、fgets にパラメーターを追加して行の最大長を制限できます。たとえば、行の長さを 80 文字に制限するには、次のコードを使用します。 $string = fgets($file_handle, 81);
「」を思い出してください。
ファイル サイズが 8 KB 以下であると仮定すると、次のコードはファイル全体を文字列に読み取る必要があります。 $fh = fopen("myfile", "rb");
$data = fread($fh, filesize("myfile"));
fclose($fh);この値より大きい場合は、ループを使用して残りを読み取ることしかできません。
fscanf
文字列処理に戻ると、fscanf も従来の C ファイル ライブラリ関数に従います。慣れていない方のために説明すると、fscanf はフィールド データをファイルから変数に読み取ります。 list ($field1, $field2, $field3) = fscanf($fh, "%s %s %s");
この関数で使用される形式文字列は、多くの場所 (PHP.net など) で説明されています。したがって、ここでは詳細には触れません。文字列の書式設定は非常に柔軟であると言えば十分でしょう。すべてのフィールドが関数の戻り値に配置されることに注意してください。 (C では、これらはすべて引数として渡されます。)
fgetss
fgetss 関数は従来のファイル関数とは異なり、PHP の機能をより深く理解できます。この関数は fgets 関数と同様に機能しますが、見つかった HTML または PHP タグをすべて削除し、プレーン テキストのみを残します。以下に示す HTML ファイルを表示します。
リスト 2. サンプル HTML ファイル
p>「痛みを与えてくれる人は誰もいないから」
の意味を理解しているなら、あなたはアメリカというバンドを聴きすぎています
次に、fgetss 関数を使用してフィルタリングします。
リスト 3. fgetss の使用
$file_handle = fopen("myfile", "r");
while (!feof($file_handle)) {
echo = fgetss($file_handle); 🎜>}
fclose($file_handle);
次は出力です: 私のタイトル
「痛みを与えてくれる人は誰もいないから」
の意味が理解できれば、アメリカというバンドを聴きすぎています
fpassthru 関数
ファイルの読み取り方法に関係なく、fpassthru を使用して残りのデータを標準出力チャネルにダンプできます。 fpassthru($fh);
また、この関数はデータを出力するため、データを取得するために変数を使用する必要はありません。
非線形ファイル処理: スキップアクセス
もちろん、上記の関数ではファイルのシーケンシャル読み取りのみが可能です。より複雑なファイルの場合は、ファイルの別の部分に行ったり来たりする必要がある場合があります。ここで fseek が役に立ちます。 fseek($fh, 0);
上記の例は、ファイルの先頭に戻ります。正確に返す必要がない場合は、キロバイトを返すように指定できます。 fseek($fh, 1024);
PHP V4.0 以降では、他のオプションがいくつかあります。たとえば、現在位置から 100 バイト前にジャンプする必要がある場合は、 fseek($fh, 100, SEEK_CUR); を使用してみてください。同様に、次のコードを使用して 100 バイト前にジャンプできます。 $fh, -100, SEEK_CUR);
ファイルの終わりの 100 バイト前に戻る必要がある場合は、SEEK_END を使用する必要があります。 fseek($fh, -100, SEEK_END);
新しい場所に到達したら、fgets、fscanf、またはその他のメソッドを使用してデータを読み取ることができます。
注: fseek は、URL を参照するファイル処理には使用できません。
トップに戻る
ファイル全体を抽出する
ここで、PHP のよりユニークなファイル処理機能、つまり、大きなデータの塊を 1 ~ 2 行で処理する機能についていくつか触れていきます。たとえば、ファイルを抽出してその内容全体を Web ページに表示するにはどうすればよいでしょうか?さて、ループを使用した fget の例を見ました。しかし、どうすればこのプロセスを簡単にできるでしょうか?このプロセスは、ファイル全体を文字列に入れる fgetcontents を使用すると非常に簡単です。 $my_file = file_get_contents("myfilename");
echo $my_file;
これはベスト プラクティスではありませんが、このコマンドは次のように簡潔に記述できます。はローカル ファイルの操作に重点を置いていますが、これらの関数を使用して他の Web ページを抽出、エコー、解析することもできることに注目してください。 echo file_get_contents("http://127.0.0.1/");
このコマンドは次と同等です: $fh = fopen("http://127.0.0.1/", "r"); $fh);
このコマンドを見て、「それでも大変だ」と思うでしょう。PHP 開発者もあなたに同意します。したがって、上記のコマンドは次のように短縮できます: readfile("http://127.0.0.1/");
readfile 関数は、ファイルまたは Web ページの内容全体をデフォルトの出力バッファにダンプします。デフォルトでは、このコマンドは失敗するとエラー メッセージを出力します。この動作を回避するには (必要な場合)、次のコマンドを実行してください。 @readfile("http://127.0.0.1/");
もちろん、本当にファイルを解析する必要がある場合は、file_get_contents によって返される単一の文字列がちょっと圧倒されます。最初の直感は、split() 関数を使用して分割することかもしれません。 $array = split("n", file_get_contents("myfile"));
しかし、これを行う便利な関数がすでにあるのに、なぜこんな苦労をするのでしょうか? PHP の file() 関数はこれを 1 ステップで実行し、行に分割された文字列の配列を返します。 $array = file("myfile");
上記の 2 つの例には若干の違いがあることに注意してください。 Split コマンドでは新しい行が削除されますが、file コマンド (fgets コマンドと同様) を使用すると、配列内の文字列に新しい行が追加されたままになります。
しかし、PHP の威力はそれをはるかに超えています。 parse_ini_file を使用すると、1 つのコマンドで PHP スタイルの .ini ファイル全体を解析できます。 parse_ini_file コマンドは、リスト 4 に示すようなファイルを受け入れます。
リスト 4. サンプル .ini ファイル
; コメント
[個人情報]
名前 = "アーサー王"
クエスト = 聖杯を求める
好きな色 = 青
[その他の情報]
Samuel Clemens = Mark Twain
Caryn Johnson = Whoopi Goldberg
次のコマンドは、このファイルを配列にダンプし、配列を出力します: $file_array = parse_ini_file("holy_grail.ini " );
print_r $file_array;
次の出力が結果です:
リスト 5. 出力
Array
(
[name] => King Arthur
[quest] ] => 聖杯を求める
[好きな色] => ブルー
[サミュエル クレメンス] => ウーピー ゴールドバーグ
)
もちろん、このコマンドがさまざまな部分をマージしていることに気づくかもしれません。これはデフォルトの動作ですが、ブール変数である 2 番目の引数を parse_ini_file: process_sections に渡すことで簡単に修正できます。 process_sections を True に設定します。 $file_array = parse_ini_file("holy_grail.ini", true);
print_r $file_array;
すると、次の出力が得られます。
リスト 6. 出力
Array
(
[ 個人情報 ] => 配列
(
[名前] => アーサー王
[クエスト] => 聖杯を求めるために
[好きな色] => ブルー
)
[詳細] => 配列
(
[サミュエル・クレメンス] => マーク・トウェイン
[キャリン・ジョンソン] => ウーピー・ゴールドバーグ
)
)
PHPデータを簡単に解析できる多次元配列に入れます。
これは、PHP ファイル処理の氷山の一角にすぎません。 tiny_parse_file や xml_parse などのより複雑な関数は、それぞれ HTML ドキュメントと XML ドキュメントの処理に役立ちます。これらの特別な関数の使用方法の詳細については、「リソース」を参照してください。これらの種類のファイルを扱う場合は、これらのリファレンスを参照する価値がありますが、この記事で説明したすべてのファイルの種類について深く考える必要はありません。これまでに説明した一般的なルールで説明した関数を操作するのに適したリファレンスをいくつか紹介します。
トップに戻る
ベスト プラクティス
プログラム内のすべてが計画どおりに実行されるとは決して考えないでください。たとえば、探しているファイルが移動されてしまったらどうなるでしょうか?権限が変更され、その内容を読み取ることができなくなった場合はどうすればよいでしょうか? file_exists と is_readable を使用して、これらの問題を事前に確認できます。
リスト 7. file_exists と is_readable の使用
$filename = "myfile";
if (file_exists($filename) && is_readable ($filename)) {
$fh = fopen($filename, " r");
# Processing
fclose($fh);
}
しかし、実際にそのようなコードを使用するのは面倒すぎる可能性があります。 fopen の戻り値の処理がより簡単かつ正確になります。 if ($fh = fopen($filename, "r")) {
# Processing
fclose($fh);
}
fopen は失敗時に False を返すため、これにより、 if ファイル処理は、ファイルが正常に開かれた後にのみ実行されます。もちろん、ファイルが存在しないか読み取り不可能な場合は、負の戻り値が予想されます。これにより、この検査で発生する可能性のあるすべての問題をチェックできるようになります。さらに、開くのに失敗した場合は、プログラムを終了するか、プログラムにエラー メッセージを表示させることができます。
fopen 関数と同様に、file_get_contents、file、readfile 関数はすべて、開くのに失敗した場合、またはファイルの処理が失敗した場合に False を返します。 fgets、fgetss、fread、fscanf、および fclose 関数も、エラー時に False を返します。もちろん、fclose を除くこれらすべての関数の戻り値を処理したことがあるかもしれません。 fclose を使用する場合、ファイル処理が正常に閉じられなくても何も行われないため、通常は fclose の戻り値を確認する必要はありません。
トップに戻る
選択はあなた次第です
PHP には、ファイルを読み取って解析するための効率的な方法が豊富にあります。ほとんどの場合、fread のような典型的な関数が最良の選択かもしれません。あるいは、readfile がそのタスクに最適な場合には、readfile のシンプルさに惹かれるかもしれません。それは実際に何が行われているかによります。
大量のデータを扱う場合は、fscanf がその価値を発揮し、split コマンドや sprintf コマンドで file を使用するよりも効率的です。逆に、わずかな変更だけで大量のテキストをエコーしたい場合は、file、file_get_contents、または readfile を使用する方が適切な場合があります。これは、キャッシュまたは一時的なプロキシ サーバーの作成に PHP を使用する場合に当てはまります。
PHP には、ファイルを処理するためのツールが多数用意されています。これらのツールの詳細を確認し、取り組んでいるプロジェクトにどれが最適であるかを確認してください。すでに多くのオプションがあるので、それらを活用して PHP でのファイルの操作を楽しんでください。