ファイルへの書き込み
そふぃのPHP入門 >> PHP実践リファレンス >> ファイル操作 >> ファイルへの書き込み

ファイルへの書き込み

ファイルへの書き込み

前回までで一通りファイルを読み込む方法を紹介しましたので、今回は書き込む方を紹介します。ファイルのデータを読み込む事ができるようになって、ついでに書き込む事もできるようになると結構色々作れます。カウンターや簡単なアクセス解析くらいならどーにかなっちゃうんじゃないかな。

もちろん、画像カウンターを作りたい、だとか高機能アクセス解析が作りたい、となってくると他の処理も必要になってきますが、簡単なものを作っておいて「他にどんな処理が必要か」という部分だけ抜き出せれば、PHPマニュアルで該当するような関数を探して結構何とかなったりします。

話がそれてきましたが、そういった「自分で探す能力」も必要だとは思いますが、ファイル操作に関しては混乱しがちなのでちゃんとスペースを取って紹介しようと思ってますのでよろしくお願いします。

fwrite関数・fputs関数―ファイルに書き込む

ファイルに書き込むにはfwrite()関数もしくはfputs()関数を使います。この2つがどう違うかというと、全く同じです。

fputs()関数はfwrite()関数の「エイリアス」といって別名、つまり全く同じ関数を名前違いで参照しているだけです。どーしてそのように2つの関数が出来上がってしまうかはPHPの歴史上の理由が多々あるのでしょうが、通常は新しい方の関数を使用する事が推奨されます。んで、エイリアスによっては古いバージョンからの互換性のためだけに残されているので新しい方を使ってくれとか書いてあったりするのですが、この2つに関して調べてみたところ、「どっちを推奨する」という記述が見当たらなかったのです。まぁ・・・本当にどっちでもいいんでしょう(笑)。マニュアルにもエイリアス関数は、「どっちかを推奨する場合もあるがどっちを使ってもいい場合もある」という趣旨の事が書かれてましたのでこの2つに関しては多分、「どっちを使ってもいい関数」なんだと思います。

どっちを使ってもいいとはいえ、混乱するのでここでのサンプルはエイリアスでない方、「fwrite()関数」でいきますが、いろいろな書籍や他のサイトでfputs()関数もよく使われていますし、私も結構使います。このサイトの他のページではサンプルがfputs()関数だったりするかもしれませんがそこら辺は気にしないで下さい。

解説

さて、前置きがだいぶ長くなりましたが、解説です。fputs()関数でも指定方法など全て同じです。

fwrite()関数・fputs()関数はファイルに文字を書き込む事のできる関数ですが、指定するのは開かれたファイルのポインタでなければなりません。つまり、fopen()関数で開いておく必要があるって事です。ファイルポインタの位置から指定した文字列を書き込んでいきます。書き込む長さを指定する事もできます。

つまり、書き込みは指定したバイト数に達したか、指定した文字列が終わりに達したかのどちらかまで行います。

参考関数

  • fwrite() ---- ファイルをバイナリ・モードで書き込む

書式

  • int fwrite( resource handle , string string [, int length ] )

返り値は書き込んだバイト数です。書き込みに失敗した場合はfalseを返します。

第1引数に開いたファイルのファイルポインタを指定します。

第2引数は書き込みたい文字列を指定します。

第3引数は省略可能なオプション引数ですが、大きいサイズを書き込もうとすると不具合が出る、だとかなんだとかいろいろ報告されているようなので一応指定しておく事をお勧めします。書き込みたい文字列の長さを指定するのは「一定長以上のデータは書き込みたくない」などの場合は便利ですが、とにかく全部書き込みたい場合など、指定する数値が特に思い浮かばなかったらstrlen()関数を使って文字列の長さを取得してしまいましょう。

参考関数

  • strlen() ---- 文字列の長さを取得する

書式

  • int strlen( string string )

filesize関数―ファイルのサイズを取得する」ではファイルサイズを取得してそれを読み込む長さとして指定しましたが、それと同じ要領です。

サンプルスクリプト

サンプルを実行する前に注意点があります。ローカル環境でのテストでは正常に書き込みなどが出来ると思いますが、これをレンタルしているサーバなどにUPして実行しようとした場合にはエラーが出るかと思います。

これはどうしてかというとファイルの「パーミッション」という「アクセス権限」が絡んでくるからです。パーミッションについてはここでは割愛させて頂きますが、ローカルでないサーバで実行させようと思ったらパーミッションの指定を行わなければいけないというのは覚えておいて下さい。ここでは一般的なパーミッションの数値を書いておきますのでとりあえずはそれを指定しておいて下さい。

さて、書き込み用のファイルの用意もして頂きます。こちらはサーバにUPするなら「666」というパーミッションを設定しておいて下さい。(606でも動くならその方が好ましいです)。サンプルでは「write_test.txt」というファイルを使っていますが、名前は何でもいいですし、テキストファイルだろうとHTMLファイルだろうと構いません。これからPHPで書き込み処理を行うのでファイルの中身も空のままでいいです。現在のフォルダにそのまま置いておいて下さい。

PHPではファイルを新規作成することもできますが、これにはファイルどころかフォルダそのものの実行権限が必要になり、セキュリティ上あまり望ましくありません。1例ですが、「ログファイルを日にち別に作成する」などのようなスクリプトだとどうしてもファイルの新規作成が必要になってきますが、スクリプト上でファイルの新規作成が必要ない場合は自分でファイルを作成しておく方が望ましいです。

  1. <?php
  2. $filepath = "write_test.txt"; // ファイルへのパスを変数に格納
  3. $string = "PHPによってこの文字が書き込まれます。"; // 書き込みたい文字列を変数に格納
  4.  
  5. $fp = fopen($filepath, "w"); // 新規書き込みモードで開く
  6. @fwrite( $fp, $string, strlen($string) ); // ファイルへの書き込み
  7. fclose($fp);
  8. //ファイルへの書き込みは終了
  9.  
  10. //現在のファイル内容を表示
  11. readfile($filepath);
  12. ?>

出力結果

PHPによってこの文字が書き込まれます。

fopen()関数のモード(第2引数)は今まで「読み込み専用モード」の「r」を使っていましたが、今回は「w」です。これは簡単に言うと「新規書き込みモード」です。ファイルの中身を空にして、先頭から書き込みを行います。つまり、ファイルポインタは先頭に置かれます。ファイルの中身を空にする事に注意して下さい。ファイルの中身は「w」で開いた時点で消えて吹っ飛びます。既にファイルに書かれているデータを保存しておきたい場合は別の処理が必要になります。

さらに、「w」モードはファイルが存在しない場合は新規作成してくれます。但し、前述のようにフォルダのパーミッションが必要になりますので今回はお勧めできません。試してみたかったらローカル内で存在しないファイル名を指定してみて下さい。きっと「w」モード君が新しいファイルを作ってくれます^^。

ちなみに「r+」というモードがあり、こちらは「上書きモード」って意味合いになるかな。「r」は読み込みのみ可能でしたが、「r+」は読み込みと書き込みの両方が可能です。こちらもファイルポインタが先頭に置かれます。ファイルに文字列があった場合は上書きしていきます。「w」との違いは、「r+」はファイルを空にせず、元のデータ上に上書きしていくという点です。「r+」モード君は指定したファイルがなくても新規作成はしてくれず、無慈悲にエラーを出力してきます。

ファイルを開いた時点では元のデータが残っているので一見こちらの方が良さそうですが、不便なところもあります。書き込みたい内容が、ファイルに既に書き込まれている文字列より短い場合には変なゴミがつきます。変なゴミ、と言いましたが、元々ファイルにあった文字列が残ってしまうって事です。先ほどのサンプルのようにシングルバイト文字(英数字)を使ってた場合なんかはそのおかげで文字化けしたりします。サンプル出しておきますので動作の違いを試してみて下さい。

  1. <?php
  2. $filepath = "write_test.txt";
  3. $string = "短い文字"; // ファイルに書き込まれている文字列より短く指定。
  4.  
  5. $fp = fopen($filepath, "r+"); // r+の上書きモードで開く
  6. @fwrite( $fp, $string );
  7. fclose($fp);
  8. // ファイルへの書き込みは終了
  9.  
  10. readfile($filepath);
  11. ?>

「結局どのモード使えばいいのよ?」というのは処理したい内容によりきり、としか言えませんがどちらも結構使われていますので、動作の違いをよく分かった上で2つとも覚えておいて下さい。