読み込み


文字データの読み込み

前回は文字データをファイルや標準出力へ出力する方法を覚えました
次は、テキストデータをファイルから読み込んで標準出力へ表示してみましょう

ファイルの読み込みにはjava.io.FileReaderクラスが使われます
このクラスは、ファイルを読み込みバイトデータの書式化を一括して行うのに便利です
コンストラクタは次の通りです

public FileReader( String fileName ) throws FileNotFoundException
public FileReader( File file ) throws FileNotFoundException
public FileReader( FileDescriptor fd )

Stringオブジェクトの場合は、そのファイルパスを参照します
FileオブジェクトやFileDescriptorオブジェクトを渡した場合、そのオブジェクトが参照しているパスを参照します

文字列を読み取るにはread()メソッドを使用します

public int read() throws IOException
public int read( char cbuf[] ) throws IOException
public abstract int read( char cbuf[], int off, int len ) throws IOException

引数に何も指定しなかった場合は、オブジェクトが指す位置の1文字を返します
読み取るごとにオブジェクトの参照(ファイルポインタ)は1文字ずつ進んでいきます
ファイルの終端にたどり着くと-1を返します

char型配列を指定すると、その配列に文字列を格納します
ストリームの終端にたどり着くと-1を返します
offとlenを指定すると、offからlenまでの一部だけを読み取ります
このメソッドの場合は、データが入力されるか、エラーまたはストリームの終端に達するまでプログラムは止まります

次のプログラムは、コマンドライン引数で指定したファイルを読み込みます
import java.io.*;

class test {
        public static void main(String args[]) {
                try {
                        FileReader fp = new FileReader(args[0]);
                        for (int i = 0 ; ; ) {
                                i = fp.read();
                                if ( i == -1) break;
                                System.out.print((char)i);
                        }
                }
                catch (IOException e) {
                        System.out.println("例外 - " + e);
                }
                catch (ArrayIndexOutOfBoundsException e) {
                        System.out.println("使い方 - java test <ファイル名>");
                }
        }
}
C言語経験者であれば、以下の説明は不要でしょう
forループに入ると、fp.read()でストリームから文字を読み取ります
read()メソッドはストリームの先頭から読み取り始め、読み取ると次の文字へ参照を移行します

ストリームがファイルの終端に達するとread()は-1を返します
これを受け取ると、ループから抜け出すようにプログラムします

返される値はint型ですが、それをchar型にキャストして出力します
こうすれば上位16ビットは無視されるので問題ありません

read()はchar型の配列へ文字列を読み込むこともできます
次のプログラムを参照してください
import java.io.*;

class test {
        public static void main(String args[]) {
                char ch[] = new char[128];
                try {
                        FileReader fp = new FileReader(args[0]);
                        fp.read(ch);
                        System.out.println(ch);
                }
                catch (IOException e) {
                        System.out.println("例外 - " + e);
                }
                catch (ArrayIndexOutOfBoundsException e) {
                        System.out.println("使い方 - java test <ファイル名>");
                }
        }
}
配列は動的に変化しないので、読み取れるのは128文字までです

さて、Java言語をここまで学習してふと思うこと…
それは、多くの言語で最初に習うはずのキーボードからの入力についてです
標準入力については、いまだに一度も触れていません

おそらく、多くのJava言語の入門書でもこの話題は前半では避けているはずです
ひとつは、データ型の変換についての問題もあります(バイナリデータと文字データ)
ですが、それ以上にJavaは入出力が非常に複雑であることが上げられます
C言語では scanf() 関数が、BASICはINPUTが、Perlは <STDIN> があります
しかし、Java言語はひとつのメソッドでポポンと言うわけにはいかないのです

プログラム言語の概念では、単純なことは単純にできなければいけないというものがありますが
JavaのI/Oは、入出力をより単純に実現したAPIがないため批判の声があげられています
実際、これまでの作業で使われたクラスの数は多いと思われます
java.ioパッケージのAPIリファレンスを見れば、初心者ならばその多さに愕然とするでしょう
ファイルの入出力で使われるクラスライブラリは、せいぜい2、3程度で十分であるはずが
汎用的であろうとするあまりに膨れ上がり、初めて使う人には使い難いものになってしまったのです
(設計者と、アプリケーションプログラマの視点の違いが招いた悪い例と言える)

と、Java言語でキーボードから入力することがいかに複雑かわかってもらえたところで説明します
実際には、複数のアプローチがあります(標準入力もストリームなので)
次のプログラムは、あまり理想的なアプローチとは言えませんが
charの配列にユーザーから文字列を入力させる場合には有効な手段と言えます
import java.io.*;

class test {
        public static void main(String args[]) {
                char ch[] = new char[32];
                try {
                        FileReader fp = new FileReader(FileDescriptor.in);
                        System.out.print("入力してください>");
                        fp.read(ch);
                        System.out.print("入力された文字列 - ");
                        System.out.println(ch);
                }
                catch (IOException e) {
                        System.out.println("例外 - " + e);
                }
        }
}
FileDescriptor.inは、標準入力へのハンドルを格納しています
これを入力ストリームとすることで、キーボードからの入力を促すことができます



前のページへ戻る次のページへ