書き込み


文字ストリーム

Java言語によるファイルへの読み書きもストリームの概念を元に行われます
ストリームは、ファイルの入出力を一貫したインターフェイスで行うことにより
プログラマはストリームを操作するだけで、異なるデバイスでのファイルの入出力を行えるのです

ストリームには、書式化したデータの文字ストリーム
バイナリデータを扱うバイトストリームがあります

文字データをファイルに書き込む場合はjava.io.FileWriterクラスがもっとも汎用的です
文字ストリームをバイトストリームに変換して出力ストリームに書き込む作業を一括してやってくれます
それらの作業を手動で設定することもできますが、この場ではデフォルトの方法を使います

FileWriterクラスのインスタンスを生成するのに、次のコンストラクタが有効です

public FileWriter( String fileName ) throws IOException
public FileWriter( String fileName, boolean append ) throws IOException
public FileWriter( File file ) throws IOException
public FileWriter( FileDescriptor fd )

Stringオブジェクト(文字列、詳しくは後記)を渡す場合は、それが直接ファイルパスとなります
これに、boolean型を渡した場合はファイルの追加か上書きかを選択することができます
デフォルトで上書きになっていますが、ここでtrueを渡すことによりファイルの終端からの追加書き込みになります

Fileオブジェクトを渡した場合は、そのFileオブジェクトが指す参照が出力ストリームとなります
FileDexcriptorも同様です。このクラスについては後記します

インスタンスが生成できれば、後はそのストリームに文字を出力します
文字の出力にはWrite()メソッドを使用します

public void write( int c ) throws IOException
public void write( char cbuf[] ) throws IOException
public abstract void write( char cbuf[], int off, int len ) throws IOException
public void write( String str ) throws IOException
public void write( String str, int off, int len ) throws IOException

int型を渡した場合、下位16ビットが書き込まれます(上位16ビットは無視)
char型の配列を渡した場合、文字配列を書き込み
Stringオブジェクトの場合は、オブジェクトの文字列を書き込みます
このときint型の off と len を指定すると、offからlen文字まで文字配列の一部を書き込みます

文字列を書き込んだ後はストリームを閉じるという作業を忘れてはなりません
CDを聴き終わったら、CDを取り出してCDケースにしまうのと同じ(?)です
なぜ閉じなければならないかというと、ストリームがバッファに文字列を保存しているからです
この文字列を、指定されたパス(宛先)に書き込むにはフラッシュと呼ばれる後処理が必要なのです

バッファをフラッシュするにはflush()メソッドを使用します
ストリームを閉じることなく、バッファをフラッシュしたいだけならばこちらを利用します

public abstract void flush() throws IOException

ストリームを閉じるにはclose()メソッドを使用します
このメソッドは、バッファをフラッシュした後直ちにストリームを閉じます
ストリームを閉じた後にwrite()やflush()をしようとすると IOExceptionがスローされます

public abstract void close() throws IOException

このメソッドを呼び出せば、バッファはフラッシュされストリームが閉じられます
以上のことをふまえて、さっそくファイルに文字列を書き込んでみましょう
import java.io.*;

class test {
        public static void main(String args[]) {
                try {
                        FileWriter fp = new FileWriter(args[0]);
                        fp.write(args[1]);
                        fp.close();
                }

                catch (IOException e) {
                        System.out.println("例外 - " + e);
                }
                catch (ArrayIndexOutOfBoundsException e) {
                        System.out.println("使い方 - java test <ファイル名> <書き込む文字列>");
                }
        }
}
コマンドラインからの実行時に、第一引数にファイルパスを、第二引数に書き込む文字列を指定します
fp.write(args[1])で、コマンドラインから与えられた文字列をバッファに書き込み
fp.close()でそれをフラッシュしています

FileWriterクラスはjava.io.OutputStreamWriterクラスを拡張しています
このクラスのインスタンス化を今おぼえる必要はありません

ファイルにデータを書き込む時に、データをエンコーディング(符号化)しています
この時に符号化の名前を得るにはOutputStreamWriterのgetEncodeing()メソッドを使用します

public String getEncoding()

このメソッドは、ストリームで使用されている符号化の名前を返します
ただし、ストリームが閉じられている場合はnullを返します
import java.io.*;

class test {
        public static void main(String args[]) {
                try {
                        FileWriter fp = new FileWriter(args[0]);
                        System.out.println(fp.getEncoding());
                        fp.close();
                }

                catch (IOException e) {
                        System.out.println("例外 - " + e);
                }
                catch (ArrayIndexOutOfBoundsException e) {
                        System.out.println("使い方 - java test <ファイル名>");
                }
        }
}
このプログラムを実行すると、その環境の符号化名(エンコーディング名)が返されます

最後に、FileWriter()コンストラクタの受け取れるオブジェクトで
まだ説明をしていないFileDescriptorクラスを説明します
このクラスはマシンの標準入出力などのハンドルを定数として定義されています
このハンドルから、標準入出力へファイルを出力することができます

public static final FileDescriptor err
public static final FileDescriptor in
public static final FileDescriptor out

errは標準エラ出力、inは標準入力、outは標準出力のハンドルを格納しています
MS-DOSなどにはリダイレクトの機能があるのはご存知でしょうか
通常、標準出力はディスプレイを指しますが必ずしもディスプレイではないのです

リダイレクトの機能を使うことで、標準出力をテキストファイルなどに変える事ができます
ここで、リダイレクトの機能を使いFileDescriptorの機能を調べてみましょう
import java.io.*;

class test {
        public static void main(String args[]) {
                try {
                        FileWriter fp = new FileWriter(FileDescriptor.out);
                        fp.write("Kitty on your lap\n");
                        fp.flush();
                        fp = new FileWriter(FileDescriptor.err);
                        fp.write("Back To Your True Shape");
                        fp.close();
                }

                catch (IOException e) {
                        System.out.println("例外 - " + e);
                }
        }
}
このプログラムを普通に実行すれば
write()メソッドで指定した文字列は両方とも画面に出力されます

Kitty on your lap
Back To Your True Shape

しかし、リダイレクトすると標準エラー出力だけが出力されるようになるはずです
コマンドラインから次のようにプログラムを実行してください

java test > test.txt

OSのリダイレクト機能によって、標準出力がtest.txtファイルに変更されています
結果として、標準エラー出力に変更してから呼び出したwrite()メソッドの文字列だけが画面に出力されます

Back To Your True Shape

その前の Kitty on your lap という文字列はtest.txtファイルに書き込まれています
これがリダイレクト機能であり、プログラミングにおける入出力で非常に重要な概念です



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