PHP の fopen / fclose — ファイルハンドルを使った操作

PHP でファイルを扱うもう一つの基本的な方法が、fopen でファイルハンドルを取得し、処理が終わったら fclose で閉じるというスタイルだ。file_get_contents のような一括操作とは異なり、ファイルを開いたまま少しずつ読み書きできるため、大きなファイルの処理やきめ細かい制御が必要な場面で力を発揮する。

fopen — ファイルを開く

fopen は第 1 引数にファイルパス、第 2 引数にモード文字列を受け取り、ファイルハンドル(リソース)を返す。

$fp = fopen('data.txt', 'r');

if ($fp === false) {
    echo 'ファイルを開けませんでした';
}

モード文字列によって、読み取り専用・書き込み専用・追記など、ファイルへのアクセス方法が決まる。

モード動作ファイルが無い場合
r読み取り専用エラー
w書き込み専用(上書き)新規作成
a追記専用新規作成
r+読み書き両用エラー
w+読み書き両用(上書き)新規作成
a+読み書き両用(追記)新規作成

w モードはファイルを開いた瞬間に内容がすべて消去される点に注意が必要だ。既存データを残したまま書き足すなら a を使う。

fclose — ファイルを閉じる

開いたファイルハンドルは、処理が終わったら fclose で閉じる。閉じ忘れるとリソースリークの原因になる。

$fp = fopen('data.txt', 'r');
// ... ファイル操作 ...
fclose($fp);

PHP のスクリプト終了時にはハンドルが自動的に解放されるが、長時間動作するスクリプトやループ内で大量のファイルを開く場合は、明示的に閉じる習慣をつけておくべきだろう。

基本的な読み書きの流れ

ファイルハンドルを使った操作は「開く → 読み書き → 閉じる」の 3 ステップが基本になる。

fopen でファイルを開く

fread / fwrite などで読み書き

fclose でファイルを閉じる

読み込みの例を見てみよう。fread はファイルハンドルと読み込むバイト数を指定して内容を取得する。

$fp = fopen('data.txt', 'r');
$content = fread($fp, filesize('data.txt'));
echo $content;
fclose($fp);

書き込みの例では fwrite を使う。

$fp = fopen('output.txt', 'w');
fwrite($fp, "1行目のデータ\n");
fwrite($fp, "2行目のデータ\n");
fclose($fp);

fwrite は複数回呼び出せるため、データを少しずつ書き込むことができる。これが file_put_contents との大きな違いだ。

バイナリモード

Windows 環境では、テキストモードとバイナリモードの違いに気をつける必要がある。テキストモードでは改行コードが自動変換されるため、画像や PDF などのバイナリファイルを扱うときはモードに b を付ける。

$fp = fopen('image.png', 'rb');
$data = fread($fp, filesize('image.png'));
fclose($fp);

rb は「読み取り + バイナリ」を意味する。Linux や macOS ではバイナリモードの指定は実質的に影響しないが、移植性を考慮して付けておくのがよい習慣とされている。

テキストモード(r, w, a)

改行コードが OS に応じて自動変換される。テキストファイルの処理に適している。

バイナリモード(rb, wb, ab)

データがそのまま読み書きされる。画像・音声・圧縮ファイルなどのバイナリデータに必須。

file_get_contents との使い分け

file_get_contents / file_put_contents は手軽だが、ファイル全体を一度にメモリに載せる。一方、fopen + fgets の組み合わせなら 1 行ずつ処理できるため、巨大なログファイルや CSV を扱うときに有利になる。

$fp = fopen('large_log.txt', 'r');

while (($line = fgets($fp)) !== false) {
    // 1行ずつ処理
    echo $line;
}

fclose($fp);

小さなファイルなら file_get_contents で十分だが、ファイルサイズが不定だったり数百 MB 以上になる可能性がある場合は、ハンドルベースの操作を選ぶほうが安全だ。メモリ消費を抑えつつ、必要なデータだけを取り出せるのがファイルハンドル方式の強みといえる。