連載
» 2007年01月24日 10時00分 UPDATE

JavaTips 〜Javaプログラミング編:java.ioパッケージのReader系クラスの使い分け

[平野正喜,@IT]

 java.ioパッケージはJ2SEで、データストリーム、直列化、およびファイルシステムによるシステム入出力用として提供されています。このパッケージに含まれる多くのクラスの中で、特に利用場面が多いのがReaderクラスをスーパークラスとする、文字ストリームを読み込むためのクラス群です。

 しかし、このReader系クラスはいくつもあり、使い分けが悩ましいところです。効率の悪い使い方をすると、ただでさえ遅い入出力処理をなおさらボトルネックにしてしまったり、読みづらいプログラムになってしまいます。

Reader系クラスの種類

 各クラスの目的と特徴をまとめると、下表のようになります。

表 java.ioパッケージのReader系クラス
クラス名 目的・概略 特徴
Reader 文字ストリームを読み込む 抽象クラスだが、単一文字を読むread()メソッドなどは実装されている
StringReader ソースが文字列の文字ストリーム Readerを直接継承。必要最小限の機能を備える
PipedReader パイプによる文字入力ストリーム Readerを直接継承。パイプによるストリームから、次の文字を読み込んだり、パイプによるリーダを、パイプによるライタに接続させられる
InputStreamReader バイトストリームから文字ストリームへの橋渡し Readerを直接継承。バイトデータを読み込んで、指定されたcharsetを使用して(または、プラットフォームのデフォルトの文字エンコーディングで)文字に変換する
FileReader 文字ファイルからの読み込み InputStreamReaderをスーパークラスとする簡易クラス。文字エンコーディングとバイトバッファのサイズはデフォルトで適切な設定がされていることを仮定している
FilterReader フィルタ処理された文字列ストリームを読み込む Readerを直接継承する抽象クラスだが、定義されているメソッドはすべて実装されている
PushbackReader 文字をストリームにプッシュバックできる文字ストリームリーダ FilterReaderをスーパークラスとする具象クラス。指定されたサイズのプッシュバックバッファを持つプッシュバックリーダを作成
CharArrayReader 文字入力ストリームとして使用する文字バッファを実装する Readerを直接継承。文字バッファはchar型の配列。現在のバッファの位置やバッファの最後のインデックスを示すフィールドを持つ
BufferedReader 文字、配列、行をバッファリングすることによって、文字型入力ストリームからテキストを効率よく読み込む Readerを直接継承。ほかの効率の良くないReader系クラスをラップすることで、バッファリングによる効率向上を与える
LineNumberReader 行番号を追跡して管理する、バッファリングされた文字入力ストリーム BufferedReaderをスーパークラスとするので効率が高い。現在の行番号を設定するメソッドと、現在の行番号を取得するメソッドが定義されている

 この中でも特に、BufferedReaderクラスの活用がキーになります。バッファリングせずにread()、readLine()を使うと、呼び出しごとにファイルからバイトを読み込み、文字型に変換し、そのたびに復帰するので、非常に効率が悪くなります。

 例えば、ファイル「a.txt」からの入力をバッファするために、下記のように記述することが推奨されています。

BufferedReader in = new BufferedReader(new FileReader("a.txt"));

バッファリング+行番号処理には、LineNumberReaderが便利

 では、使い分けの一例を挙げましょう。

 BufferedReaderクラスに比べると活用の度合いが小さいようですが、BufferedReaderクラスのサブクラスであるLineNumberReaderはなかなか便利なクラスです。

 現在の行番号を設定するsetLineNumber(int)メソッドと、現在の行番号を取得するgetLineNumber()メソッドを持ち、しかも、BufferedReaderクラスのサブクラスですから、読み込みの効率も高いのがポイントです。

 一例として、テキストファイルを行読みして、空行でなければ、その行の番号と内容を出力するプログラムを作成すると、以下のようになります。

図 LineNumberReaderクラスの利用例 図 LineNumberReaderクラスの利用例

 なお、setLineNumber(int)メソッドは、ストリーム内の現在位置を実際に変更するのではなく、getLineNumber()から返される値を変更するだけですので、ご注意ください。

Profile

RunDog.org

平野正喜


Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。