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 |
コメント