第
第3
3章
章.
.フ
ファ
ァイ
イル
ルを
を用
用い
い
たデ
た
デー
ータ
タ入
入出
出力
力
【学習のねらい】
① データをファイルへ出力する(書き込む)方法を学習する。 ② データをファイルから入力する(読み込む)方法を学習する。 大量のデータを処理する場合は、ファイルからデータを読み込んでから処理を行います。 また、プログラムが終了すると変数に記憶されたデータは消えてしまうので、処理結果を 残すためにはファイルに保管しておくことが必要になります。このようにファイルを用い たデータ入出力はコンピュータを使った処理の場合必須の技術です。そこで本章では、Java 言語を用いたファイルによるデータ入出力の仕方を学習しましょう。3-1 ファイルへの出力1-ファイルへの書き込み方
まず、簡単な例でデータをファイルに書き込む方法を学びましょう。次のようなフレーム を作成してください(作成の際、プロジェクト名はKiso3_1 として下さい)。 そしてボタンクリック時のプログラムを次のように記述してください。 <プログラム>private void jButtonWriteActionPerformed(ActionEvent evt) {
String data=jTextFieldData.getText();
try { ⑥
// ファイル Test1.txt を出力ストリーム fw として定義する
FileWriter fw= new FileWriter("Test1.txt"); ①
// fw への出力時にバッファリング機能をつける。
BufferedWriter bw= new BufferedWriter(fw); ②
// さらに出力時に便利なメソッドを使用可能にする。
PrintWriter fout = new PrintWriter(bw); ③ fout.print("出力データ:"+data); //ファイルへの書き込み ④ jLabelMessage.setText("書き込み終了しました。"); fout.close(); //ファイルを閉じる ⑤ } catch(Exception em) { ⑥ jLabelMessage.setText("エラー発生:"+em); } } jButtonWrite jTextFieldData jLabelMessage
加えてプログラム(NewJFrame.java)の先頭行に以下の波線部を加えて下さい。以下、フ ァイルへの入出力を行う場合、これは必ず(毎回)必要になります。 import java.awt.event.ActionEvent; ・・・ import javax.swing.SwingUtilities; import java.io.*; 見慣れない命令が目につきますが、それらの説明の前にまずは実行して動作を確認して みましょう。このプログラムは、入力文字列欄に入力した文字列を「Test1.txt」というフ ァイルに出力する(書き込む)プログラムです。確認のため、プログラムを起動させ入力 文字列欄に「これはテスト出力です。」と入力し、[書き込み]ボタンをクリックして下さ い。 すると、「待機中」というメッセージが「書き込み終了しました。」というメッセージに 変わります。このとき、プログラム(プロジェクト)と同じフォルダ内(今の場合「Kiso3_1」 内)に「Test1.txt」というファイルができています。そこで、メモ帳や秀丸エディタなど の適当なテキストエディタで開き、次のように出力されていることを確認してください。 <プログラムの解説> 0.ストリームについて Java 言語では入出力データをストリームという概念で表します。ストリームとは流れと いう意味です。”流れ”と言われても最初はピンと来ないかもしれませんが、大量のデータ をファイルに書き込むあるいは読み出す様は、まさにデータが流れて行くように見えるた めストリームと呼ばれているようです。Java 言語では、ファイルへのデータ入出力はスト リームの制御(ストリームの行き着く先はどこか?→出力ファイルの指定、ストリームは どこから来るのか→入力ファイルの指定、ストリームをどのように区切って入出力する か?等々)を行うことによって実現されます。Java 言語では、ストリームを制御するため に各種のクラスを用意しています。以下、ファイルへの出力に用いられる FileWriter、 BufferedWriter そして PrintWriter というクラスの用い方を上の例を用いて解説しましょ う。①、②などの番号は、p.29 のプログラム中に付した番号に対応しています。 出力データ:これはテスト出力です。 <Test1.txt>
① 出力ファイルの定義-FileWriter クラス
FileWriter fw= new FileWriter("Test1.txt");
によって、FileWriter クラスのオブジェクトを fw という名前で生成しています。一般に、 あるクラスのオブジェクトを生成するためには、 クラス名 オブジェクト名 = new クラスのコンストラクタ と記述します。クラスの定義やオブジェクトの生成については、「プログラミング」テキ ストの第7章で学習しました。忘れてしまった人はテキストを読み返して下さい。さて、 FileWriter クラスの場合、右辺のコンストラクタ FileWriter()のカッコ内に引数とし て出力ファイル名を指定します。この文によって、ここで扱うストリームfw が、ファイ ル「Test1.txt」に流れ着く出力ストリームとして定義されるのです。 ② 出力ストリームをバッファリング可能にする-BufferedWriter クラス ファイルへデータの出力を行う場合、データ(ストリーム)を1単位(通常はバイト単 位)毎に転送すると、ハードディスクなどファイル媒体側の受け入れ準備ができるまで待 ち時間が発生し効率が悪くなります。そこで、一旦、出力データをメモリにため込み(書 き込み)、ファイル側の書き込み準備ができた段階で順次データを書き込む処理が行われ ます。この処理をバッファリングと言います。
BufferedWriter bw= new BufferedWriter(fw);
によって、bw はバッファリング機能付きのストリームとなります。 ③ サービス機能を付加する-PrintWriter クラス
ファイルへのデータ出力を行う場合、PrintWriter クラスに用意されている print() あるいは println()メソッドを用いるのが普通です。*)そのため、次の文によって出力 ストリームをPrintWriter クラスの提供するサービス機能つきのストリームにしました。
PrintWriter fout = new PrintWriter(bw);
なお、上では説明のために3つに分解して記述したのですが、通常は出力ストリームの定 義は次のように1行で(一度に)記述されます。
PrintWriter fout = new PrintWriter(new BufferedWriter(new FileWriter("Test1.txt"))); 本講義でも以下ではこのように1行で記述することにします。 *)少し補足すると、FileWriter クラスにもデータを書き込む write()というメソッド が用意されているのですが、実数値を出力できない、またデータの改行を指定できな いなど、実用上不便な点が多かったので、PrintWriter クラスの print()および println()クラスが用意されたのです。
④ ファイルのクローズ
ファイル処理を終了したら、close()メソッドにより、必ずファイルを閉じなければな りません。
⑤ エラー処理-try~catch 文
FileWriter fw= new FileWriter("Test1.txt");
などのように、出力ストリームを定義する際、何らかの理由で指定したファイルを出力フ ァイルとして確保できなかった場合、(FileWriter クラスは)IOException という例外情 報を発行します。Exception(例外)とは、想定通りに行かなかった場合、つまりエラー が発生した状態を指すプログラミング用語です。Java 言語では、Exception 情報を発行 する事を、”Exception 情報を投げる”と言います。そして投げられた Exception 情報を キャッチ(catch)して(エラーに対応した)適切な処理を行うよう、文法的に義務づけ ています。一般に、ファイルの入出力を行う場合、 try { ファイル入出力の処理 }
catch (Exception em){
エラーに対応した処理 } という形で処理を記述します。今の場合、エラー処理は catch(Exception em) { jLabelMessage.setText("エラー発生:"+em); } となっており、これは、エラー情報を(ラベルに)表示させる処理を行うという意味です。 catch 文の()内の引数 em には Exception の情報、つまりエラーメッセージが書き込まれ ているのです。 少し説明が長くなりましたので、実際に色々な動作を確認することで理解を深めましょ う。上のプログラムに以下の波線部を追加して実行してみて下さい。 void jButtonWrite_actionPerformed(ActionEvent e) { String data=jTextFieldData.getText(); try { ・・・ fout.print("出力データ:"+Data); //ファイルへの書き込み fout.print(”次の出力"); jLabelMessage.setText("書き込み終了しました。"); ・・・ 以下同じ ファイル 入出力の場 合 の定型の書き方
先程と同様に文字列入力欄に「次の出力」と入力してボタンをクリックすると、ファイル 「Test1.txt」の内容は次のようになっているはずです。 つまり、print()メソッドを連ねると、該当文字列が(横に)続けて出力されます。 それでは、 というように、改行して出力するにはどうしたらよいでしょうか? そのためには、最初の print()メソッドを println()メソッドに変更すればよいのです。次のように書き換えて 実行してみて下さい。今度は、上のように改行して出力されるはずです。 fout.println("出力データ:"+Data); //ファイルへの書き込み fout.print(”次の出力"); このように println()文は()内の文字列を出力後改行する、という意味を持ちます。
【基礎課題 3-1】
上の例では、文字列を採り上げましたが、整数でも同様に出力できます。 上のプログラムに波線部の修正および点線枠の追加を行って実行して下さい。 ・・・ fout.println("出力データ:"+Data); //ファイルへの書き込み fout.println("次の出力"); int a=2,b=5; fout.println("a="+a+" b="+b); fout.println("a+b="+(a+b)); jLabelMessage.setText("書き込み終了しました。"); ・・・ そして、「Test1.txt」にどのように出力されるかを確認し、枠内を埋めて下さい。 <Test1.txt の出力結果> 出力データ:これはテスト出力です。次の出力 <Test1.txt> 出力データ:これはテスト出力です。 次の出力 出力データ:これはテスト出力です。 次の出力 a=2 b=5 a+b=7<解説> 文字列同士を「+」で結ぶと、それは連結を意味する、ということはこれまで学習した通 りです。しかし、上のプログラムでは整数型と文字列型を「+」記号で結んでいます。「そ んなことが許されるのか?」と首をかしげた人もいることと思いますが、Java 言語ではこ のような書き方を認めています。そして結果を確かめてみれば分かるとおり、整数と文字 列が連結されて表示されます。例えば次のようなプログラムを考えた場合、 int a=2; String ans="a="+a; 文字列型変数ans の値は「a=2」となります。このように、文字列と整数を+記号で結ぶと、 整数が自動的に文字列化され、文字列の連結として処理されます。これは非常に便利なの で、Java 言語では頻繁に利用されます。 もちろん、実数についても同様です。例えば int a=2; String ans="a/4="+(a/4.0); というプログラムを実行すると、文字列型変数ans の値は「a/4=0.5」となります。
3-2 ファイルへの出力2-ダイアログによるファイル名の指定
3-1節では、出力ファイル名が固定されているものとして、プログラム中で直接ファ イル名を指定していました。しかし、実際には、プログラム実行時にファイル名を指定で きた方が便利です。次の課題でその方法を学習しましょう。【基礎課題 3-2】
前節と同様、次のようなフレームを作成してください。 次に、ファイル名を指定することができる「JFileChooser」というコンポーネントを使 用します。その使い方は次の通りです。指示にしたがって設定して下さい。<JFileChooser の使用方法>
まず、コンポーネントパレットの「More Components」タブにある「JFileChooser」コ ンポーネントを選択(クリック)して下さい。 続いて、Eclipse ワークベンチの右側にある「アウト ライン」ビューの「inst –NewJFrame・・・」をクリック して下さい。 すると、次ページの「コンポーネント名」指定画面が 現れるので、ここでは、「jFileChooser1」のまま、[OK] ボタンをクリックします。 jButtonWrite jTextFieldData jLabelMessageすると、JFileChooser の表示内容であるファイル名指定画面がフレーム上に表示されま す。 表示をフレームに戻すために、「アウトライン」ビュー の「this – JFrame・・・」(フレームを意味します)をクリ ックします。すると、フレームが表示されるようになりま す。これで、JFileChooser コンポーネントが使用可能に なりました。 次ページへ進んで下さい。
以下の課題では、幾つかのファイルをデータ入出力に用います。そこで、それらファイ ルを一括して管理できるよう、適当な場所にファイル保管用のフォルダ 「IOFile」を作成しておいて下さい。フォルダ名は何でも良いのですが、 以下では、ファイル保管用フォルダ名が「IOFile」という名前であるとし て説明しています。 そしてボタンクリック時のプログラムを次ページのように作成します。
private void jButtonWriteActionPerformed(ActionEvent evt) { String data=jTextFieldData.getText(); try { // ダイアログボックスを開く jFileChooser1.showSaveDialog(this); ① // 出力ファイル名を指定する File fName=jFileChooser1.getSelectedFile(); ② // 出力ストリームを定義する
PrintWriter fout=new PrintWriter(new BufferedWriter (new FileWriter(fName))); ③ fout.println("出力データ:"+data); //ファイルへの書き込み jLabelMessage.setText("書き込み終了しました。"); fout.close(); //ファイルを閉じる } catch(Exception em) { jLabelMessage.setText("エラー発生:"+em); } } なお、プログラムの先頭に、 import java.io.*; を追加することを忘れないようにして下さい。ファイル名を指定している①~③以外は前 節のプログラムと同じです。その説明は後回しにして、とりあえずプログラムを実行して みましょう。 実行後、前節同様次のような起動画面が現れます。 ここで次ページのように、入力文字列欄に「これはテスト出力です。」と入力し[書き込 み]ボタンをクリックすると・・・ p.30 で説明した通り、プログラムの先頭です。メソッド 内の先頭ではありませんので注意して下さい。
次のように出力ファイル指定のためのダイアログボックスが現れます。ここで、次のよう に、先程作成した「IOFile」フォルダを指定します。 さらに、ファイル名として「output.txt」を入力し、[保存]ボタンをクリックすると・・・ ダイアログボックスは消え、元の画面に戻ります。 この時点で、出力ファイル「output.txt」に入力文字列欄に指定した文字列が書き込まれて います。確認のため、[IOFile]フォルダ内の「output.txt」ファイルの中身を適当なエデ ィタでチェックしてみて下さい。次のように書き込まれているはずです。 このように、JFileChooser コンポーネントを用いると、プログラム実行時に任意のファ 出力データ:これはテスト出力です。 <output.txt>
イルを指定することができます。それでは、次ページで先程のプログラムの①~③の意味 を確認しておきましょう。 <プログラムの解説> ① showSaveDialog()メソッドにより、保存先のファイルを指定するダイアログボック スが表示されます。()内は通常this を指定するものと理解しておいて下さい。 ② getSelectedFile()メソッドは、ファイルダイアログボックスで指定したファイル 名を返します。ファイル名は「File」クラス(型と考えて結構です)の変数(オブジ ェクト)に代入できます。ここでは、その変数名を「fName」としています。 ③ 下線部に示したように、今まで"output.txt"等と直接ファイル名を指定していた部 分をファイル名の変数 fName に置き換えています。
3-3 ファイルからの入力1-ファイルからの読み込み方
さて、本章の後半では、ファイルからのデータ入力の方法を学習することにします。 例として【基礎課題3-2】で作成した出力ファイル「output.txt」を読み込んでその内容 を表示させるプログラムを考えましょう。【基礎課題 3-3】
次のようなフレームを作成してください。 【基礎課題3-2】と同様に入力ファイルを実行時にファイルダイアログボックスで指定する ので、p.35 で説明した通り JFileChooser コンポーネントを設定して下さい。そして、ボタ ンクリック時のプログラムを次のように記述します。private void jButtonReadActionPerformed(ActionEvent evt) { String data;
try {
jFileChooser1.showOpenDialog(this);
File fName=jFileChooser1.getSelectedFile();
BufferedReader fin=new BufferedReader ② (new FileReader(fName)); data=fin.readLine(); //ファイルからの読み込み ③ jTextFieldData.setText(data); //読み込んだデータの表示 fin.close(); jLabelMessage.setText("読み込み終了しました。"); }
catch (Exception em) {
jLabelMessage.setText("エラー発生:"+em); } } ※ プログラムの冒頭に、「import java.io.*;」を追加することを忘れないように注意 して下さい(p.30 参照)。 <プログラムの解説> ① ダイアログボックスで指定した(入力)ファイル名を受け取る部分は出力ファイルの 場合と同じです。ただし、入力先のファイルを指定するダイアログボックスを開く際に jButtonRead jTextFieldData jLabelMessage ①
② 入力ストリーム「fin」の指定(定義)です。出力ストリームの場合と比べて PrintWriter クラスに該当する部分がありませんが、それ以外は出力ストリームの場合と同様です。 ③ readLine()メソッドは、入力ストリーム(今の場合ファイル「fName」)から1行分 だけ読み込み、その値を文字列として返します。 プログラムの内容はほぼ理解できると思いますので早速実行して動作を確認してみまし ょう。 このプログラムを用いればどの様なファイルでも、その内容を表示させることができ ます。ただし、最初の1行分だけですが・・・。 このプログラムを起動し、[ファイル からの入力と表示]ボタンをクリッ クします。 すると、ファイル指定のためのダ イアログボックスが現れるので、 ここで、【基礎課題3-2】で作成し た「output.txt」を指定します。 ファイル名の指定後、[開く]ボタ ンをクリックすると・・ 元 の 画 面 に 戻 り 、 フ ァ イ ル 「output.txt」の内容が表示されま す。
【基礎課題 3-4】- 複数行のデータの読み込み
今度は、複数行のデータをファイルから読み込んでみましょう。入力フ ァイルとして、科目の HP の該当部分に掲載している「input.txt」ファ イルをダウンロードし、前節で作成したフォルダ「IOFile」にコピーして 下さい。このファイルには、次のように、あるテストの5人分の得点がデ ータとして入力されています。今、このファイルからデータを読み込み、 このテストの平均点を表示するプログラムを考えましょう。 作成するプログラムの動作内容は次の通りです。 55 60 92 38 71 <input.txt> プログラムを起動すると左のよ うな画面が現れます。 ここで、[データの読み込み]ボタ ンをクリックすると・・・ 入力ファイルを指定するダイアロ グボックスが開くので、ここで、 今ダウンロードしたファイル 「input.txt」を指定します。その 後[開く]ボタンをクリックする と・・・ 元の画面に戻り、表示が「読み込 み終了しました。」に変わります。 この時点で入力データの読み込み は完了しています。 続いて[平均点]ボタンをクリック すると、テストの平均点が表示され ます。 jButtonRead jButtonAvg jTextFieldAvgそれではプログラムを作成しましょう。今の場合、簡単のためにデータの個数は5つであ ることが分かっていることにしましょう。作成に当たってポイントとなるのは次の点です。 ① 5つのデータ(得点)を保管するために、大きさが5の配列型変数を用意する。 ② ファイルから1行ずつデータを読み込む方法は【基礎課題 3-3】で分かっているので、 5つのデータを読み込むには、それを5回繰り返せば良い。 ③ 今の場合、読み込んだデータ(得点)を保管する配列型変数は、ボタン[データの読 み込み]とボタン[平均点]の2つのイベントハンドラ(メソッド)で共有(参照)す るので、配列型変数の宣言は、メソッドの外で行わなければならない。なぜならメソッ ドの中で宣言すると、そのメソッド内でしか参照できないからである。→「プログラミ ングⅡ」テキスト「6-12 ローカル変数とインスタンス変数」参照。 以上を念頭に置いてプログラムを記述すると次のようになります。
int[] tokuten=new int[5]; //得点を保管する配列(整数型)
int num; //データの個数
private void jButtonReadActionPerformed(ActionEvent evt) { String data;
try {
jFileChooser1.showOpenDialog(this);
File fName=jFileChooser1.getSelectedFile(); BufferedReader fin=new BufferedReader
(new FileReader(fName));
// ファイルからの読み込み
num=5; //データ個数の設定
for (int i=0;i<num;i++) { data=fin.readLine(); tokuten[i]=Integer.parseInt(data); } jLabelMessage.setText("読み込み終了しました。"); fin.close(); }
catch (Exception em) {
jLabelMessage.setText("エラー発生:"+em); }
}
private void jButtonAvgActionPerformed(ActionEvent evt) {
// 平均点の計算
int sum=0;
for (int i=0;i<num;i++) { sum=sum+tokuten[i]; }
double avg= sum/(double)(num); ③ jTextFieldAvg.setText(String.valueOf(avg)); } ① ② 得点の合計の計算 [データの読み込み]ボタン [平均点]ボタン
<プログラムの解説> ① 5つのデータを保管する整数型配列変数 tokuten とデータの個数を保管する整数型変 数num を宣言します。場所は、メソッド(イベントハンドラ)の外側ならどこでも良 いのですが、ここでは、分かりやすく[データの読み込み]ボタンクリック時のイベン トハンドラの上に置きました。 ② データの個数分だけ(1行ずつ)データを読み込み、それを tokuten[i]に順次代入 しています。データを読み込んだ段階では文字列型なので、tokuten[i]に代入する際 には整数型への変換が必要であることに注意して下さい。 ③ ここで平均点を計算しています。Java 言語のルールにより、「整数/整数」は小数点以 下が切り捨てられ整数になる、という点に注意して下さい。そのため、分母のnum を 実数型に型キャスト(変換)しています。型キャストについては「プログラミングⅠ」 テキストp.84 を参照して下さい。 プログラム作成後は実行して動作を確認して下さい。
3-4 ファイルからの入力2-連続したデータ読み込み
【基礎課題3-4】では予め入力データの個数が分かっているものとしていましたが、実際 にはデータの個数が分からない状態で入力処理を行う場合が少なくありません。そこで次 の課題で、ファイル中のデータの個数が予め分かっていない場合に対応できるように(【基 礎課題3-4】のプログラムを)改良しましょう。【基礎課題 3-5】
【基礎課題3-4】のプログラムにおいて、配列の大きさを下線部のように修正し、データ 読み込み部分を枠線部のように修正して下さい。それ以外は以前の通りです。int[] tokuten=new int[
100
]; //得点を保管する配列 ① int num; //データの個数private void jButtonReadActionPerformed(ActionEvent evt) { String data;
try {
jFileChooser1.showOpenDialog(this);
File fName=jFileChooser1.getSelectedFile(); BufferedReader fin=new BufferedReader
(new FileReader(fName)); // ファイルからの読み込み int i=0; while ((data=fin.readLine())!=null) { tokuten[i]=Integer.parseInt(data); i++; } num=i; //データの個数の保管 jLabelMessage.setText("読み込み終了しました。"); fin.close(); }
catch (Exception em) {
jLabelMessage.setText("エラー発生:"+em); } } <プログラムの解説> ① 予めデータの個数が決まっていないので、予想される最大個数程度を配列の大きさに 指定しておきます。ここでは100 にしています。 ② readLine()メソッドによって、ファイル中の最終データの次を読み込んだ場合、そ こには何もないので、「null」という特別の値になります。null は「空っぽ」という意 味です。「while ((data=fin.readLine())!=null)」では、入力ストリームから ② [データの読み込み]ボタン
読み込んだ値を data に代入し、その値が「null」ではない場合、つまりデータが存在 する限り読み込み続ける、という条件指定になっています。なお、while ループ内の処 理を行う回数は「データの個数」に等しいので、カウンタi がそのままデータの個数に なっています。 上のように修正後、プログラムを実行し、前節同様きちんと動作することを確認して下 さい。
【基礎課題 3-6】
【基礎課題3-5】のプログラムに、以下のように最高点を求め表示するボタンを加えて下 さい。 下の枠内を埋めて最高点を求めるプログラムを完成させて下さい。private void jButtonMaxActionPerformed(ActionEvent evt) { int max=tokuten[0];
for(int i=1; i<num;i++) {
} jTextFieldMax.setText(String.valueOf(max)); } ヒント 最高点を求める処理は、「2-3 配列の応用-最大・最小を求める」の【基礎課題 2-4】(p.23) と同じです。 入力ファイルを指定してデー タを読み込んだ後、[最高点] ボタンをクリックすると、最 高点が表示される。 jTextFieldMax jButtonMax
【応用課題 3-A】
【基礎課題3-6】に今度は、(下のように)最低点を求める処理を加えて下さい。【応用課題 3-B】
HP の該当部分より、あるテストの得点の入ったファイル「score.txt」 をダウンロードして下さい。そして、【応用課題3-A】のプログラムを用い て、このテスト得点のデータの平均点および、最高点、最低点を求めて下 さい。 ※ このデータは100 名以上です。配列の大きさを 150 に変更して下さい。 55 90 85 38 80 ・・・ 70 62 67 75 <score.txt> 次に、左のように、[デー タの読み込み]ボタンをク リックした時に受験者人 数を表示するように拡張 して下さい。 加えた部分【応用課題 3-C】
さらに【応用課題3-B】を拡張しましょう。今、テストの得点が 50 点以上であれば合格 であるとしましょう。そこで、「score.txt」から得点を読み込んで、[合格者]ボタンをクリ ックすると、合格者数を表示する部分を加えて下さい。
3-5 1行に複数のデータがある場合のデータ読み込み
3-4 節で、ファイルからデータを読み込む際の一般的な方法を学習しました。しかし、そ こでは、1行に一つのデータが書き込まれていることが想定されていました。ところが実 際の場面では、ファイルの1行に複数のデータが書き込まれている場合が少なくありませ ん。その際は、個々のデータを区切って読み込む事が必要になります。本節では、このよ うにファイルの1行に複数のデータが存在する場合の読み込み方を学習します。【基礎課題 3-7】
HP の該当部分から、ファイル「score2.txt」をダウンロード して下さい。このファイルには右のように、あるテストの結果 が、氏名と得点という形で保管されています。そして、氏名と 得点はカンマ記号「,」で区切られています。 そこで、このファイルから、氏名と得点を(別々に)読み込 み、その氏名だけを表示するプログラムを作成しましょう。(基 本的な部分は【基礎課題3-5】のプログラムと同様です。異なる のは、「氏名」と「得点」という2つのデータを読み込むという 点のみです。) なお、ダウンロードしたファイル「score2.txt」はこれまで同 様、フォルダ「IOFile」に保存されているものとします。 作成するプログラムの動作結果は以下の通りです。 花形 満 ,55 轟 次郎 ,63 金田正太郎,39 鮎原こずえ,87 浅丘ユミ ,48 矢吹 丈 ,70 東 八郎 ,35 星 明子 ,77 諸星 団 ,59 伊達直人 ,44 <score2.txt> jButtonRead jTextArea1 jButtonDisplay jLabelMessage プログラムを起動すると、次 の画面が現れます。 ここで、[データ読み込み] ボ タ ン を ク リ ッ ク す る と・・・なお、フレームの設計に当たっては、3-2 節で学習した通り、JFileChooser コンポーネン トを設定しておく事を忘れないようにして下さい(pp.35~36 参照)。 それでは、プログラムの作成に取りかかりましょう。まず、プログラムの冒頭部に以下 の2行(波線部)を追加して下さい。 import java.awt.event.ActionEvent; ・・・ import javax.swing.SwingUtilities; import java.io.*; import java.util.*; 「java.io.*」が必要なのはこれまで通りですが、「java.util.*」が必要なのは、こ の中に、複数のデータを区切って読み込む機能を有するクラスが入っている(そしてここ でそれを利用する)からです。 [データ読み込み]ボタンのイベントハンドラ、および、氏名と得点を保管する配列、 入力ファイルを指定するためのダ イアログボックスが現れます。 ここで、ダウンロードしたファイ ル「score2.txt」を指定し、[開く] ボタンをクリックします。 すると、データの読み込みが 完了し「読み込み終了しまし た。」というメッセージが表示 されます。 続いて[表示]ボタンをク リックすると、テキストエリ アに、読み込んだ受験者の全 員の氏名が表示されます。
String[] name=new String[100]; //氏名を保管する配列
int[] tokuten=new int[100]; //得点を保管する配列
int num; //データの個数
private void jButtonReadActionPerformed(ActionEvent evt) { String data;
try {
jFileChooser1.showOpenDialog(this);
File fName=jFileChooser1.getSelectedFile(); BufferedReader fin=new BufferedReader
(new FileReader(fName)); int i=0;
while ((data=fin.readLine())!=null) {
StringTokenizer tk=new StringTokenizer(data,","); ① name[i]=tk.nextToken(); tokuten[i]=Integer.parseInt(tk.nextToken()); i++; } num=i; jLabelMessage.setText("読み込み終了しました。"); fin.close(); }
catch (Exception em) {
jLabelMessage.setText("エラー発生:"+em); } } 枠線部以外は、基本的に【基礎課題3-5】と同様なので説明は省きます。ここでは、新し く出てきた「StringTokenizer」クラスについて説明すれば十分でしょう。 <StringTokenizer クラスについて>
① StringTokenizer tk=new StringTokenizer(data,",");
によって、StringTokenizer クラスのオブジェクト(変数と考えて結構です)を「tk」と いう名前で生成しています。 一般に、「new StringTokenizer(文字列,区切り記号)」という形で生成したオブジェ クトには、「文字列」の中身が「区切り記号」で分解され、各々が順に(文字列として) 保管されます。上の例で具体的に説明しましょう。ファイルの最初の1行が変数 Data に 読み込まれとき、data の中身は次のようになっています。 変数 data の中身 花形 満 ,55
そして、「StringTokenizer tk=new StringTokenizer(data,",");」によって、 data の中身は区切り記号「,」によって分解され、tk の中身は次のようになります。
② [データの読み込み]ボタン
1番目のトークン 2番目のトークン tk 花形 満 55 区切られた個々の文字列を「トークン」と呼びます。 ② StringTokenizer クラスには、「nextToken()」メソッドがあり、これによりtk に 保 管 さ れ て い る ト ー ク ン を 順 に 取 り 出 す こ と が で き ま す 。 今 の 場 合 、 最 初 の nextToken()メソッドで「氏名」が取り出され、2番目の nextToken()メソッドで得 点が取り出される訳です。 以上のように、StringTokenizer クラスを利用することにより、任意の区切り記号で 区切られたデータを順次取り出すことができます。 次に、[表示]ボタンのイベントハンドラは次の通りです。
private void jButtonDisplayActionPerformed(ActionEvent evt) { String data="";
for (int i=0;i<num;i++) { data=data+name[i]+"\n"; } jTextArea1.setText(data); } 氏名を(1行に1名ずつ)順に表示させるので、「name[i]+改行記号」を連結させた結 果を、jTextArea1 に表示させています。 プログラムを作成したら実行し、動作を確認して下さい。 [表示]ボタン キーボード上では半角の「¥」です。使用 フォントによっては¥と表示されます。