PHP の fread・fgets・fgetcsv — 読み込み関数の使い分け
PHP にはファイルからデータを読み込む関数が複数用意されている。fread はバイト単位で読み取り、fgets は 1 行ずつ読み取り、fgetcsv は CSV の 1 行を配列として返す。それぞれ得意な場面が異なるため、目的に応じた選択が重要になる。
fread — バイト単位の読み込み
fread はファイルハンドルから指定したバイト数だけデータを読み込む関数だ。テキストでもバイナリでも扱える汎用的な関数で、読み込むサイズを自分で制御できる。
$fp = fopen('data.txt', 'r');
$content = fread($fp, 1024); // 最大1024バイト読み込み
fclose($fp);ファイル全体を読み込みたい場合は、filesize と組み合わせる。
$fp = fopen('data.txt', 'r');
$content = fread($fp, filesize('data.txt'));
echo $content;
fclose($fp);ファイルの終端に達すると、指定バイト数に満たなくても読み込みが終わる。ファイルポインタが末尾かどうかは feof で確認できる。
$fp = fopen('data.bin', 'rb');
while (!feof($fp)) {
$chunk = fread($fp, 8192);
// チャンク単位で処理
}
fclose($fp);この方法なら巨大なファイルでもメモリを大量に消費せず、8KB ずつ処理を進められる。
fgets — 1 行ずつの読み込み
fgets は改行文字(\n)またはファイル終端まで読み取り、1 行分の文字列を返す。テキストファイルを行単位で処理するときの定番だ。
$fp = fopen('log.txt', 'r');
while (($line = fgets($fp)) !== false) {
echo trim($line) . "\n";
}
fclose($fp);fgets が返す文字列には末尾に改行が含まれるため、trim や rtrim で除去するのが一般的だ。第 2 引数で最大読み込みバイト数を制限することもできる。
$line = fgets($fp, 256); // 最大255バイトまで読み込み非常に長い行があるファイルでも、バイト数を制限しておけばメモリの使いすぎを防げる。
バイト数を指定して読み込む。バイナリファイルやチャンク処理に向いている。
改行までを 1 行として読み込む。テキストファイルの行単位処理に最適。
fgetcsv — CSV の 1 行を配列で取得
fgetcsv は CSV 形式のファイルを 1 行読み込み、各フィールドを配列として返す。自分でカンマ分割する手間が省けるうえ、ダブルクォートで囲まれたフィールド内のカンマも正しく処理してくれる。
$fp = fopen('users.csv', 'r');
while (($row = fgetcsv($fp)) !== false) {
echo "名前: {$row[0]}, 年齢: {$row[1]}\n";
}
fclose($fp);デフォルトの区切り文字はカンマだが、第 3 引数で変更できる。タブ区切り(TSV)の場合は次のようにする。
$row = fgetcsv($fp, 0, "\t");第 2 引数の 0 は行の最大長を自動判定させる指定だ。
ヘッダー行の処理
CSV ファイルの先頭にヘッダー行がある場合、最初の 1 行を読み飛ばすか、カラム名として活用するのが一般的な手法だ。
$fp = fopen('products.csv', 'r');
$headers = fgetcsv($fp); // ヘッダー行を取得
while (($row = fgetcsv($fp)) !== false) {
$product = array_combine($headers, $row);
echo "{$product['name']}: {$product['price']}円\n";
}
fclose($fp);array_combine でヘッダーをキーにした連想配列を作ると、$row[0] のようなインデックスアクセスより可読性が大幅に向上する。
文字エンコーディングの注意
日本語を含む CSV を扱うとき、エンコーディングの問題にぶつかることがある。Excel で作成された CSV は Shift_JIS(CP932)であることが多いが、PHP 内部では UTF-8 で処理するのが標準的だ。
$fp = fopen('data_sjis.csv', 'r');
while (($row = fgetcsv($fp)) !== false) {
$row = array_map(function ($field) {
return mb_convert_encoding($field, 'UTF-8', 'SJIS-win');
}, $row);
// UTF-8 に変換して処理
echo implode(' | ', $row) . "\n";
}
fclose($fp);エンコーディングの自動判定は不安定なので、ファイルの出所がわかっている場合は SJIS-win のように明示的に指定するのが安全だ。
Shift_JIS の Windows 拡張。丸囲み数字やローマ数字など、CP932 固有の文字も正しく変換できる。
3 つの関数の使い分け
どの読み込み関数を選ぶかは、ファイルの形式と処理の粒度で決まる。バイナリデータやチャンク処理なら fread、テキストの行処理なら fgets、CSV なら fgetcsv というのが基本的な判断基準になる。いずれも fopen / fclose と組み合わせて使うため、ファイルハンドルの管理を忘れないようにしたい。