第10章 ファイルを操作してみよう

10.2 ファイル入力処理

ファイル入力処理とは、外部のファイルを利用できるようにプログラム内に読み込むことを指します。ファイル入力処理を行いたい場合、前節で紹介したファイルシステム関数を利用することで行えます。
ファイル入力処理では、以下に示すファイルシステム関数を利用していきます。

  • fopen関数:ファイルをオープンする。(読み込みモード)
  • feof関数:読み込む行(データ)がファイルの終端でないか確認する。
  • fgets関数:ファイル内のデータを1行ずつ取得する。
  • fgetcsv関数:ファイル内のデータの1行データ(csv形式)を配列データに変更して取得する。
  • fclose関数:ファイルをクローズします。

詳しい関数の使い方や説明は、サンプルプログラムと合わせて順次説明していきます。

10.2.1 テキストファイルを読み込んで利用しよう

ファイルを読み込んで利用するには、先ず初めに「fopen関数」でファイルをオープンする必要があります。この関数を使うことで、外部のファイルの中身を参照できる状態にできます。

書式:ファイルオープンとデータ読み取り

表 10.2.1:ファイルオープン関数の主なモード一覧

上記以外のモードもありますが、この3つを覚えておけば問題ありません。他のモードを知りたい方は関数リファレンスを参照して下さい。

凡例:ファイルオープンとデータ読み取り

fopen関数の戻り値は、処理が成功するとファイルを操作するための「位置情報(ファイルポインタ)」を、失敗した場合には「false」を返します。そして、この位置情報をfgets関数で利用することで、ファイルデータを読み取ることができます。fgets関数は1回呼び出すと、位置情報を次の行へ移動させる仕組みにもなっています。

実際にプログラムを作成して確認してみましょう。

ファイルから1行データを読み出すプログラム

テキストファイルをオープンして1行ずつデータを読み出し、Web画面にそのデータが表示されることを確認します。

オープンファイルの準備

プログラムを作成する前に、Eclipseの機能を使ってオープンするファイル「sample.txt」の準備をしましょう。

①フォルダーの作成


図 10.2.1: ch10フォルダー作成

②ファイルの作成


図 10.2.2:ファイル作成1

③新規ファイル作成


図 10.2.3:ファイル作成2

④ファイル作成確認


図 10.2.4:ファイル作成3

⑤ファイル内容の記述

以下に示す内容を「sample.txt」ファイル内に記述して保存する。


図 10.2.5:ファイル作成4

Eclipse機能を利用してのファイル作成

Eclipseの機能を利用してテキストファイル(.txt)を作成しましたが、その他の形式(.csv、.html等)のファイルを作成したい場合もこの機能を利用して行えます。
「ファイル名.拡張子」の拡張子を作成したい形式に変更すれば、色々なファイルを作成することができます。

ソース・フォルダー: myproj_basic/ch10
パッケージ: readFileShowData.php
アクセスURL:http://localhost/myproj_basic/ch10/readFileShowData.php

readFileShowData.php

実行結果

解説

8行目でfopen関数を使って「sample.txt」を読み込みモードでオープンしています。第1引数にファイル名だけを指定した場合、readFileShowData.phpと同じディレクトリ内が参照先になります。

8行目の処理を行うことで、変数$fpがsample.txtのファイル実体の位置情報(ファイルポインタ)を指し示すようになります。


図 10.2.6: ファイルオープンイメージ

10行目でファイルの位置情報が格納された変数$fpをfgets関数の引数に設定して、オープンしたファイルデータの1行目のデータを取得して画面に表示しています。

fgets関数は読み出し位置の1行目のデータ(■世界の挨拶「こんばんは」)を取得(※①)して、次の読み出し位置を次の行の先頭に設定(※②)します。そして戻り値として取得したデータ(■世界の挨拶「こんばんは」)を画面に表示します。(※③)


図 10.2.7: 読み込みデータの読み取り1回目

11行目で再度fgets関数を利用して、オープンしたファイルデータの2行目のデータを取得して画面に表示しています。

fgets関数は読み出し位置の2行目のデータ(日本語はこんばんは)を取得(※①)して、次の読み出し位置を次の行の先頭に設定(※②)します。そして戻り値として取得したデータ(日本語はこんばんは)を画面に表示します。(※③)


図 10.2.8: 読み込みデータの読み取り2回目

14行目で変数$fp をfclose関数の引数に設定して、最後にファイルクローズ処理を行います。

fopenとfgets関数を使ってデータを1行づつ読み出す仕組みは学習できました。次の項では繰り返し文とfeof関数を組み合わせて、ファイルデータ全て取り出す仕組みについて学習していきます。

10.2.2 ファイル内のデータを全て読み込んでみよう

オープンするファイルデータは、データ量が固定されているものもあればそうでない場合もあります。固定データではない場合に前項で学習した1つずつ読み出す仕組みでは、合計で何回読み出せばいいのか判断することができません。
固定でもそうでない場合でも、データ量を判断してその分だけ読み出せるようにプログラムを組むのが一般的になります。ファイルデータは繰り返し文とfeof関数を組み合わせて利用することで、データ量分だけ取り出すことが可能になります。

凡例:繰り返し文とfeof関数を使って全てのデータを読み込む

feof関数の引数もファイルオープンした際の戻り値である位置情報になります。この位置情報から現在の位置が終端になっていないか確認してくれます。feof関数の戻り値は終端でなければfalse、終端であればtrueを返すため、whileの条件式では「!」を使って結果を反転させます。そうすると繰り返し処理は終端でなければtrueになり条件式を満たせるため、データ読み出しで終端へ移動するまで継続する仕組みになります。
また、ループ内でfgets関数を呼び出さないと「位置情報(ファイルポインタ)が移動せず、無限ループになってしまう」ため必ずセットで利用するようにして下さい。

ファイルデータ最終行の空行について

PHPでは読み込んだファイルのデータの最終行が改行されていると、その行も読み取りデータの1行と判断します。空行を扱ってしまうと意味のない処理になってしまうケースが多いので、最終行の空行が不要であれば入れないようにしましょう。

ファイル内のデータを全て読み込んで表示するプログラム

繰り返し文とfeof関数を利用して、オープンしたファイルデータを全てWeb画面に表示します。

ソース・フォルダー: myproj_basic/ch10
パッケージ: readFileShowAllData.php
アクセスURL:http://localhost/myproj_basic/ch10/readFileShowAllData.php

readFileShowAllData.php

実行結果

解説

8行目でファイルを読み込みモードでオープンします。

11~13行目で繰り返し処理とfeof関数を組み合わせて、ファイルの終端までのデータを全て読み込む処理を行っています。

ここで重要なのは「feof関数」の役割です。この関数の役割は読み込んだデータの現在の読み出し位置をチェックし、終端であれば「true」そうでなければ「false」を返してくれます。これを「while文」と組み合わせることで、終端でなければ内部の処理(データ1行読み出して、画面に表示する)を行い、終端であれば繰り返し処理が終わる仕組みになります。そうすることで全てのデータを読み込むことが可能になります。


図 10.2.9: 繰り返し処理を利用して全データの読み込み

16行目でデータの読み出しが終わったので、忘れずにファイルをクローズします。

今回のプログラムのように繰り返し文とfeof関数を組み合わせて利用すれば、簡単に全データを読み込むことができますので、この仕組みをしっかりと理解しておきましょう。

10.2.3 csvファイルを読み込んで利用しよう

csv(Comma Separated Values「カンマ・セパレーテッド・バリュー」)ファイルとは、「,(カンマ)」で区切られたデータの形式のファイルのことを言います。単純にカンマで区切られたデータとなっており汎用性が高く、異なるアプリケーションソフト間のデータ交換に使われることが多いです。テキストファイルの拡張子が「.txt」であるのに比べて、csvファイルは拡張子「.csv」となります。

PHPでcsvファイルを扱う場合には、テキストファイルの時の操作と全く同じで行えます。ただ、データを1行ずつ読み込む場合にfgets関数を使えばそのまま1行を単純に読み込めますが、fgets関数とは別の「fgetcsv関数」を利用すると、読み込んだ1行のデータをカンマで区切って配列データとして返してくれます。

凡例:fgetcsv関数で1行のCSV形式データを読み込む

fgetcsv関数を使うとカンマを区切りにして、分割できる数分だけ配列に格納されます。もしも、カンマが無い場合でも、その行データを配列変数[0]に格納するため、fgetcsv関数の戻り値は必ず「配列型」になることを覚えておいて下さい。またfgetcsv関数を呼び出すと、fgets関数と同じように位置情報も次の行へ移動します。
凡例の読み込んだ1行データが「69,95,92,32,56」だった場合のイメージは、以下のようになります


図 10.2.10: fgetcsv関数を使った場合の配列データの格納状況

では、実際にcsvファイルをオープンしてfgets関数とfgetcsv関数の両方を使って確認してみましょう。

csvファイルをオープンしてデータ読み込み方法の違いを確認するプログラム

csvファイルをオープンし、fgets、fgetcsv関数の両方で1行データを読み出した場合の違いをWeb画面に表示して確認します。

読み込みファイルの準備

Eclipse機能のファイルを作成する方法で、以下の内容のcsvファイルを「ch10フォルダー直下」に作成して下さい。

subject_data.csv

ソース・フォルダー: myproj_basic/ch10
パッケージ: readCsvFile.php
アクセスURL:http://localhost/myproj_basic/ch10/readCsvFile.php

readCsvFile.php

実行結果

解説

8行目でcsvファイルである「subject_data.csv」を読み込みモードでオープンします。テキストファイルでもcsvファイルでもfopen関数を利用するのは変わりません。

11行目で読み込んだファイルの位置情報を元にfgets関数で1行読み込み、その情報をvar_dump関数を使って画面に表示しています。実行結果の画面に「string(11) “国語,68 “」と表示され、1行データがそのまま読み込まれているのが確認できます。

14行目ではfgetcsv関数を使って1行読み出し、その情報をvar_dump関数を使って画面に表示しています。fgetcsv関数は読み出した1行データをカンマで区切って配列データにするので、実行結果から「array(2) { [0]=> string(6) “数学” [1]=> string(2) “78” }」と配列データになっているのが確認できます。

17行目でファイルのクローズを行います。csvファイルでもオープンした情報は必ずクローズするようにしましょう。

今回のプログラムではfgetcsv関数の仕組みを確認しただけで、分割したデータを利用することはありませんでしたが、fgetcsv関数はカンマでデータを分割してくれるため、自分で分割処理を記述せずにデータを直ぐ利用できるのが最大のメリットになります。
csvファイルを使ったファイル処理を次の節でも行いますので、その時にfgetcsv関数で読み出した配列データを扱うプログラムを紹介します。fgets関数とfgetcsv関数の違いをしっかりと覚えておいて下さい。

ポイント
  • ファイルをオープンする場合fopen関数を利用する。
  • 読み込みモードでファイルをオープンしたい場合は、第2引数に「r」を設定する。
  • 読み込んだファイルデータから1行読み込みたい場合fgets関数を利用する。
  • 読み込んだファイルデータを全て読み込みたい場合、繰り返し文とfeof関数を利用することで行える。
  • fgetcsv関数を利用すれば、読み込んだ1行データをカンマで分割し配列データにしてくれる。
  • オープンしたファイルは処理が終わった後、fclose関数を使ってクローズ処理を行う。

NEXT>> 10.3 ファイル出力処理