【PHP入門2021】ファイルに書き込み・上書きする関数file_put_contentsの使い方

PHP

file_put_contents関数の基本構文

データをファイルに書き込みます。

このfile_put_contents関数はfopen/fcloseなども自動で実行してくれます。

そのため便利ですがループの中で使う場合ループ分open/closeを繰り返すことになるので非常に遅くなりますので、数十回以上のループをするような場合は絶対に使用しないようにしてください。

バッチ処理などで一つの処理で数万回のログを追記する場合などに使いがちですがこの使い方は最悪です。自分でファイル開閉のタイミングが把握できる場合は使うべきではありません。

逆にWebアクセスによる独自のログの追記などはいつアクセスがあるかわからないのでそのたびにファイルの開閉をするしかありません。こういったケースはfile_put_contentsを使っても問題ありません。

また、file_get_contentsとは違ってフラグでロックを指定することができます。
ファイルがない場合は新規作成します。

file_put_contents ( string $filename , mixed $data , int $flags = 0 , resource $context = ? ) : int

パラメータ

名前 初期値 説明
string $filename ファイルの名前やパス
mixed $data 書き込むデータ。文字列や配列、ストリーム リソースのどれか
int $flags 0 付与する機能をフラグで指定 ※後述の表参照
resource $context stream_context_create()で作成したコンテキストリソース

フラグ

$flagsには以下のフラグを | で組み合わせて指定できます。

設定値 機能
FILE_USE_INCLUDE_PATH PHP設定値include_path のファイルを検索
FILE_APPEND ファイルを上書きではなく追記。指定しないといったんファイルを空にして書き込む上書きとなる。
LOCK_EX 排他ロック(書き込みロック)。書くときに使う。他人は読むのも書くのも禁止

返り値(戻り値)

説明
int 書き込んだバイト数。失敗時はfalse

書き込む先のディレクトリがない場合などWarningが発生します。

file_put_contents関数の使い方

ファイルから一気に全部読み込んで、別ファイルに書き込むサンプルソースコード

//=======================================================
// ファイルから一気に全部読み込んで、別ファイルに書き込むサンプル
//=======================================================

$read_file = 'input/line-100000.txt'; //読み込みファイル
$write_file = 'output/line-100000.txt'; //書き込みファイル

echo "処理開始 コピー {$read_file} => {$write_file}" . PHP_EOL;

$file_data = file_get_contents($read_file); //ロックなし
file_put_contents($write_file, $file_data, LOCK_EX); //ロック指定可能

echo "書き込みファイルの行数: " . count(file($write_file));

ダメな使い方(繰り返しが多いループの中で使う)のサンプルソースコード

これは絶対やってはいけない例です。1つのプロセスの中で繰り返し使うとopen/close処理を含むfile_put_contentsでは無駄が多すぎます。

この例では1000回でデータ量も少ないので、数秒しかかかりませんが、数万、数十万と繰り返していくとかなりのロスになるので気を付けておきたいポイントです。file_put_contentsのせいで10倍遅いなどになりかねません。

//=======================================================
//file_put_contentsのダメな使い方(繰り返しが多いループの中で使ってしまう)
//=======================================================

$write_file = 'output/line-1000.txt'; //書き込みファイル
for($idx=0; $idx<=1000; ++$idx){
	file_put_contents($write_file, $idx . PHP_EOL, LOCK_EX | FILE_APPEND);
}
echo "書き込みファイルの行数: " . count(file($write_file));

エラーハンドリングする場合のサンプルソースコード

戻り値がエラーの際にfalseになることを利用します。
詳細の内容はWarningとして出力されるのでそれを参照します。

//=======================================================
// file_put_contentsエラー処理のサンプル
//=======================================================

$read_file = 'input/line-100000.txt'; //読み込みファイル
$write_file = 'output/line-100000.txt'; //書き込みファイル

echo "処理開始 コピー {$read_file} => {$write_file}" . PHP_EOL;

try {

	$file_data = file_get_contents($read_file); //ロックなし
	if($file_data !== false){
		echo "ファイルの読み込みに成功しました" . PHP_EOL;
	}else{
		throw new Exception("ファイルの読み込みに失敗しました");
	}

	$write_result = file_put_contents($write_file, $file_data, LOCK_EX| FILE_APPEND); //ロック指定可能
	if($write_result !== false){
		echo "ファイルの書き込みに成功しました({$write_result}byte)" . PHP_EOL;
		echo "書き込みファイルの行数: " . count(file($write_file));
	}else{
		throw new Exception("ファイルの書き込み失敗しました");
	}

}catch(Exception $ex) {
	echo "【エラー終了】" . $ex->getMessage() . PHP_EOL;

}finally{
	//正常、エラー関係なく最後に実行する処理
}

関連するファイルシステム関数

ファイル入出力関数の特徴まとめ

関数 利用シーン 機能 処理単位 ハンドル
の管理
ロック 速度 メモリ節約 安全性 エラー時
fgetc 1文字ずつ処理する 読み 1文字ずつ 別途 別途 × △自前 終端でfalse
fgets 1行ずつ処理する 読み 1行ずつ 別途 別途 △自前 終端かエラー
でfalse
fread 固定バイトごとに
処理する
読み 指定バイト 別途 別途 ○一括
×分割
×一括
○分割
△自前 エラーでfalse
fgetcsv CSVファイルを
1行ずつ読み込む
読み 1行ずつ 別途 別途 × △自前 エラーで0かnull
file ロック不要のファイル
を行ごとに高速処理
&同時アクセスが少ない
読み データ全部 不要 ロックなし × × エラーでfalseや
E_WARNING
file_get_contents ロック不要のファイル
の文字列全体を高速取得
&同時アクセスが少ない
読み データ全部 不要 ロックなし × × エラーでfalseや
E_WARNING
fwrite
fputs
ハンドル利用時の
書込処理全般
書き 指定バイト 別途 別途 ○一括
×分割
×一括
○分割
△自前 エラーでfalse
fputcsv CSVを1行ずつ書込時 書き 1行ずつ 別途 別途 × △自前 エラーでfalse
file_put_contents 1~数回だけ書込する時。
繰り返しは非常に遅い。
書き データ全部 不要 ロック指定可能 ○一括
×分割
×一括
○分割
△フラグ指定 エラーでfalse

ファイルシステム関数一覧

fopen

fclose

flock

feof

fgetc

fgets

fread

fwrite/fputs

fgetcsv

fputcsv

file

file_get_contents

file_put_contents

コメント

タイトルとURLをコピーしました