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

ファイルの読み込み2

ファイルの読み込み

ファイルの読み込み1」で紹介した関数と違い、今回は、fopen()関数でファイルを開いた後に読み込みの処理をしたいと思います。またもや読み込みだけだと分かりにくいので、ついでに表示までします。処理の流れは以下のようになると思います。

  1. ファイルを開く
  2. ファイルの内容を読み込む
  3. ファイルを閉じる
  4. 読み込んだ内容を表示する

1番と3番は「ファイル操作の基本」で紹介しましたし、4番はまぁ・・echo()文かprint()文が無難なところです。今回紹介するのは2番の処理を実現する関数になると思います。

ちなみにファイルを閉じた後なのに、どうしてファイルの内容を表示できるのか疑問に思ったら、「変数」を思い出してください。ファイルの内容を読み込んだら、その値を変数に格納しておくので、ファイルを閉じても変数の値は残ります。

fread関数―ファイルを読み込む

解説

今度のfread()関数もファイルの内容を取得します。今までに紹介した中でにもfile_get_contents()関数やfile()関数はファイルの内容を全て取得するという関数ですし、readfile()関数を使うと全て取得してくれた上に表示までしてくれました。では、何が違うかというと、今回のfread()関数は引数の指定にファイルポインタ(ハンドラ)を使用するという事で、上記の関数のように直接ファイル名を指定する事はできません。

また、第2引数に読み込むバイト数を指定する事でファイル全てを読み込まず、読み込む長さを変えることもできます。

参考関数

  • fread() ---- ファイルをバイナリ・モードで読み込む

書式

  • string fread( resource handle , int length )

第1引数にfopen()関数で取得したファイルポインタ(リソース型)を指定する事になります。

第2引数に読み込みたいバイト数を指定します。つまり、読み込みは第2引数で指定したバイト数に達したか、ファイルの終端(EOF)に達したかのいずれかまで行います。

読み込まれたファイルの内容を文字列として返します。

サンプルスクリプト

ここで読み込むファイルの中身は今までと同じでこうなってます。文字化けする場合はブラウザのメニューから「表示」→エンコード→UTF-8を選択して下さい。

fopen()関数のモード(第2引数)は「ファイル操作の基本」で解説した「r」モードです。これは「読み取り専用モード」となり、書き込みとかはできないモードです。今回は読み込む処理がメインになるので「r」しか使いません。

fread()の簡単な使用例

  1. <?php
  2. $handle = fopen('sample.txt','r'); // ファイルを開いてファイルポインタを取得
  3. $contents = fread( $handle, 1024 ); // ファイル内容を1024バイト分読み込んで変数に格納
  4. fclose( $handle ); // ファイルを閉じてファイルポインタを破棄
  5. echo $contents."<br />\n"; // 変数に格納しておいたファイル内容を出力
  6. ?>

出力結果

サンプルテキストです。 2行目です。 ついでにこれは3行目です。 この行で終了です。

filesize関数―ファイルのサイズを取得する

さて、上記のサンプルでは第2引数の「読み込むバイト数」を直接1024と指定していますが、ファイルを全て読み込みたい場合など、ファイルサイズをいちいち調べてから記述するなんてのは不便です。そこで、ファイルサイズを取得してくれる関数もありますのでついでに紹介しておきます。

参考関数

  • filesize() ---- ファイルサイズを取得する

書式

  • int filesize( string filename )

引数に指定したファイルのサイズを取得してくれますが、fread()関数と違い、ファイル名を指定する事に注意して下さい。

filesize()とfread()の組み合わせ

  1. <?php
  2. $filename = 'sample.txt'; // ファイル名を変数に格納
  3. $handle = fopen( $filename ,'r');
  4. // ファイルサイズ分読み込んで変数に格納
  5. $contents = fread( $handle, filesize($filename) );
  6. fclose( $handle );
  7. echo $contents."<br />\n";
  8. ?>

このようにする事でファイルのサイズをいちいち調べる必要がなくなるので便利です。

fgets関数―ファイルから1行読み込む

解説

fgets()関数はファイルの内容を1行取得して返してくれます。こちらも引数の指定にはファイルポインタ(ハンドラ)を使用する事で、上記2つの関数のように直接ファイル名を指定する事はできません。

fgets()関数でも読み込む長さを指定する事ができます。つまり、こちらの読み込みは第2引数で指定したバイト数に達したか、改行文字があったか、ファイルの終端(EOF)に達したかのいずれかまで行います。

参考関数

  • fgets() ---- ファイルから1行取得する

書式

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

fgets()関数は読み込みに失敗した場合にfalseを返します。また、ファイル終端に達した時にもfalseを返します。

第1引数にはfopen()関数で取得したファイルポインタ(リソース型)を指定する事になります。

第2引数の「長さ」は読み込むバイト数です。fgets()関数の第2引数はオプション引数で省略した場合は行の終わりまで読み込みを続けます。

但し、PHPのバージョンによってこの動作には若干の違いがあるようです。オプション引数となったのはPHP4.2.0からのようですし、PHP4.3以前で省略した場合は1024バイト(つまり1kバイト)がデフォルト値として適用されていたようです。さらに、1行のサイズが大きいと読み込む時に不具合が出る可能性も十分あります。現在はオプション扱いのこの引数ですが、そのような事情のためちゃんと指定しておいた方が無難だとは思います。

実際に読み込むサイズは第2引数の「長さ-1」バイト分になります。

サンプルスクリプト

ここで読み込むファイルもfread()関数の時と同じなので説明は省略させてもらいます。

fgets()の簡単な使用例

  1. <?php
  2. $fp = @fopen('sample.txt','r');
  3. //fgetsがFALSEを返す(通常はファイル終端に達した時)までループ
  4. while( $line = fgets($fp,1024) ){ // バイト数の1024に深い意味はありません
  5.   echo $line."<br />\n";
  6. }
  7. fclose($fp);
  8. ?>

出力結果

サンプルテキストです。
2行目です。
ついでにこれは3行目です。
この行で終了です。

1行ずつ処理ができるので、ループ文(ここではwhile)で処理ができ、行末に改行を付けながら表示する、何て事も可能になります。

ファイルポインタについて

さて、今まで「ファイルポインタ」の存在を解説せずに済むように避けて通って来たのですが、そろそろ解説しておかないとこの先大変なので解説します。

ファイル操作の基本」でも説明したように、ファイルポインタというのはファイルを操作するためのハンドルという意味でも使われているようですが、現在ファイルのどの位置にいるかを示すポインタって意味でもあります。テキストエディタなどだと現在の編集点で、「|」マークがちかちかしてたりすると思いますが、そういったファイル内での現在位置を示すものを「ファイルポインタ」と言います。これが配列だと「配列ポインタ」なんて言われます。

上記のfgets()関数だと、読み込んだ部分までファイルポインタが移動します。ファイルポインタが移動してくれているので次の行の先頭から行末までの読み込みが可能になり、ループ文での処理が可能になるわけです。

分かりにくいと思うのでどうゆう事が起こってるか順番に書いておきます。

  1. ファイルを開く(fopen関数)
  2. ファイルを開くモードが「r」なのでファイルポインタはファイルの先頭に置かれる
  3. ファイルを1行読み込んだら、その1行分を$lineに格納(while文の条件式)
  4. (この時点でファイルポインタは1行目の行末というか2行目の先頭に移動)
  5. 変数に格納しておいた$lineを、改行「<br />」つけて表示(echo文)
  6. ファイルポインタの位置から行末までの1行(つまり2行目)を$lineに再代入
  7. (この時点でファイルポインタは2行目の行末というか3行目の先頭に移動)
  8. 再代入した$lineを改行付きで表示・・・・・・・・・・・・とループしていく。
  9. ファイルの終端(EOF)に達した時点でfgets()関数がfalseを返す
  10. falseになるとwhile文から抜けるので、ループ終了。
  11. 開いたファイルは閉じておく(fclose関数)

つまり・・・・fgets()関数は現在のファイルポインタの位置から1行分読み込むという働きを持ってます。毎回毎回上のように流れを考える必要はありませんが、ファイルポインタの位置というのは常に把握しておかないとファイルの読み書きの時に困ります。ファイルポインタの概念が分からないとファイル操作もどんどん理解が追いつかなくなってきますのでがんばって把握して下さい。

ちなみに、fopen()関数の第2引数(モード)ですが、rモード(読み取り専用モード)ではファイルポインタが先頭に置かれます。これは各モードごとに決められています。モードは今のところ「r」だけ覚えておいて下さい。新しいモード出したら解説します。興味のある方は解説関数リファレンスのfopen()関数にモードのリストを載せてますので参考にどうぞ。