ファイル関連クラス

Javaのファイルの扱い

このサイトで紹介してきたサンプルは、コンソールに文字を表示するなどの処理を中心に説明してきましたが、ここではそれらの情報をデータとして保存をしておくための1つの方法として、ハードディスクなどにファイルで出力し保存するしたり、それを読み出す方法について説明していきます。Javaにはファイルを扱える様々なクラスがありますが、主要なものをピックアップして紹介していきます。

Fileクラス

ファイルの生成・存在の確認

まずは、最も基本となるFileクラスを見てみましょう。Fileクラスは、java.ioパッケージのクラスで、コンピューター内のファイルやディレクトリを、オブジェクトとして扱うことができるようにするクラスです。まずは、ファイルの生成・および、存在を調べるサンプルを実行してみましょう。以下のサンプルは、「c:¥test」というフォルダにファイルを作成します。なので、実行前に、cドライブ直下にtestフォルダを作ってください。

ClassSample01.java
package class1;

import java.io.*;

public class ClassSample01 {
	public static void main(String[] args){
		try{
			File file = new File("c:¥¥test¥¥filesample.txt");	// Fileクラスのインスタンスを作成
			System.out.println(file.exists());					// ファイルの有無を調べる
			System.out.println(file.createNewFile());			// ファイルの生成
		}catch(IOException e){
			System.out.println("処理に失敗しました。");
		}
	}

}
実行結果(1回目)
false
true

実行すると、以上のような結果が出ます。すると、testフォルダの中に「filesample.txt」というファイルができているので、確認してください。そして、2回目の実行結果は以下のようになります。

実行結果(2回目)
true
false

ではなぜ、このような結果になるのでしょうか。プログラムの内容について説明していきましょう。

プログラムの内容

8行目では、まずファイル名を指定してオブジェクトを作成します、そして、そのファイル名のファイルが実際にあるかどうかをexists()メソッドで確認しています。ただ、最初の段階では、ファイルが存在しないので、falseが返ってきています。これはそのファイル名のファイルが実際にディスク上にないことを表しています。そして、10行目のcreateNewFile()で、ファイルを生成します。ここでのtrueは作成に成功したことをあらわしています。

また、2回目の実行では、すでにファイルが出来上がっているので、exists()メソッドの値がtrueになり、すでにファイルが出来上がっていることから、ファイルの作成ができないため、createNewFile()メソッドではfalseが帰ってくるのです。

ファイル・フォルダの一覧の取得

Fileクラスのつかいかたはこれだけではありません。次は、ファイルやフォルダの存在を調べるプログラムをみてみましょう。以下のサンプルを実行する前に、testフォルダ内に、hoge,fugaという2つのフォルダを作ってください。

ClassSample02.java
package class1;

import java.io.*;

public class ClassSample02 {
	public static void main(String[] args){
		File fi = new File("c:¥¥test");
		File[] fiList = fi.listFiles();
		System.out.println("指定したディレクトリは、" + fi.getAbsolutePath() + "です。");
		for(int i = 0; i < fiList.length; i++){
			if(fiList[i].isFile() == true){
				System.out.println("ファイル名は、" + fiList[i].getName() + "です。");
			}else if(fiList[i].isDirectory() == true){
				System.out.println("ディレクトリ名は、" + fiList[i].getName() + "です。");
			}
		}

	}

}
実行結果
指定したディレクトリは、c:\testです。
ファイル名は、filesample.txtです。
ディレクトリ名は、fugaです。
ディレクトリ名は、hogeです。

9行目のgetAbsolutePath()メソッドでは、ファイルクラスのインスタンスの絶対パスを得ることができます。更に、10行目のlistFiles()メソッドで、そこにあるファイルおよびフォルダの一覧を、Fileクラスのインスタンスの配列として取得できます。

これらの内容は、isFile()およびisDirectory()クラスで、それがファイルか、それともディレクトリかを調べることができます。このフォルダ内には、先ほど作成したnewFile.txtというファイルがありますので、実際にファイルが作成されているのを確認できました。

ファイルの書き込み・読み込み

FileWriterクラス

JavaのAPIでは、データをファイルに書き込み・読み込みためのクラスが用意されています。それが“FileWriterクラス”と“FileReaderクラス”です。まずは、ファイルを書き込むFileWriterクラスを見てみまそう。以下のサンプルを実行してみてください。なお、実行するには、cドライブ直下にtestフォルダを作成しておく必要があります。

ClassSample03.java
package class1;

import java.io.*;

public class ClassSample03 {
	public static void main(String[] args){
		try{											//例外処理
			FileWriter fw = new FileWriter("c:¥¥test¥¥File1.txt");	//ファイルのオープン
			for(int i = 1; i <= 5; i++){
				fw.write(i + "行目¥r¥n");
			}
			fw.close();										//ファイルのクローズ
		}catch(IOException e){
			System.out.println("書き込みに失敗しました。");
		}
	}

}

プログラムを実行してみた結果、コンソールにはなにもできません。しかし、「c:¥test」フォルダ直下に、File1.txtというファイルができており、内容は以下のようになっています。

図1-1.File1.txtの中身

File1.txtの中身

プログラムの内容

では、プログラムの中身を見てみましょう。8行目の処理で、FileWriterクラスを生成することにより、書き込み用ファイルが生成されます。ファイル名は、コンストラクタの引数として与えられます。ファイルの書き込みは、10行目のwrite()メソッドで行われます。最後に、12行目のclose()メソッドによって、ファイルがクローズされ、ファイルが書き込まれます。

ファイルの改行記号

ところで、9行目のエスケープシーケンスである、¥r¥nですが、これは改行を意味します。ただし、気をつけなくてはならないのは、ファイルの改行に用いられるエスケープシーケンスは、OSによって異なるという点です。なお、この改行はWindowsがOSの場合ですが、OSごとの改行記号は以下のようになります。(表1-1.)

表1-1:OSごとに用いられる改行記号
OS 改行記号 エスケープシーケンス
WINDOWS CR + LF ¥r¥n
Unix/Linux系 LF ¥n

FileReaderクラス

続いて、ファイルの読み込みを見てみましょう。ClassSample03で書き込んだファイルで書き込んだファイルを読み込んで表示するサンプルを見てみましょう。以下のサンプルを実行してみてください。

ClassSample04.java
package class1;

import java.io.*;

public class ClassSample04 {

	public static void main(String[] args){
		FileReader fr = null;					//finallyで使うのでここで宣言
		try{									//例外処理
			fr = new FileReader("c:¥¥test¥¥File1.txt");		//ストリームのオープン
			int c;											//char型なのでintに代入
			while((c = fr.read()) != -1){	//文字が無かったら-1が返る
					System.out.print((char)c);		//int型をchar型に型変換
			}
		}catch(FileNotFoundException e1){
			System.out.println("ファイルが見つかりません。");
		}catch(IOException e2){
			System.out.println("ファイルエラーです。");
		}finally{
			try{								//ここでも例外処理が必要
				if(fr != null) fr.close();		//nullでなければここでファイルクローズ
			}catch(IOException e){
				System.out.println("ファイルクローズい失敗しました。");
			}
		}
	}
}
実行結果
1行目
2行目
3行目
4行目
5行目
ガーベージコレクタの起動を促す
System.gc();

ファイルの生成により、ファイルにアクセス(10行目)し、close()(21行目)で終了するというのはでは、FileWriterクラスと変わりません。

12行目のFileReaderクラスのread()メソッドを使って1文字ずつ取り出し、何もなかった場合に戻り値として得られる-1の時whileを抜けるようにしています。文字コードで代入されるのでint型で受け取り表示する時にchar型に型変換しています。

filallyブロックでは、frがnullでないときだけclose()メソッドを実行しています。FileWriterオブジェクトの場合も、特別なケースを除いて、このようにfinallyブロックでのクローズ処理が適切です。

flush()メソッド

最後に、一つのファイルを書きながら読み込むパターンを紹介します。通常、FileWriterクラスでは、close()メソッドを実行して初めてファイルに対して書き込みが行われます。しかし、flush()メソッドを用いれば、ファイルをクローズしなくても、書き込み処理が行われます。以下のサンプルを実行してみてください。

ClassSample05.java
package class1;

import java.io.*;

public class ClassSample05 {
	public static void main(String[] args){
		FileWriter fw = null;
		FileReader fr = null;					//finallyで使うのでここで宣言
		try{
			String fileName = "c:¥¥test¥¥File2.txt";
			fw = new FileWriter(fileName);	//ストリームのオープン
			fr = new FileReader(fileName);	//ストリームのオープン
			fw.write("あいうえお¥r¥n");			//文字の出力①
			fw.write("かきくけこ¥r¥n");			//文字の出力②
			fw.flush();							//ここでフラッシュ
			fw.write("さしすせそ¥r¥n");			//文字の出力③
			int c;								//char型なのでintに代入
			while((c = fr.read()) != -1){		//文字が無かったら-1が返る
				System.out.print((char)c);	//int型をchar型に型変換
			}
		}catch(FileNotFoundException e){
			System.out.println("ファイルが見つかりません。");
		}catch(IOException ee){
			System.out.println("ファイルエラーです。");
		}finally{
			try{
				if(fw != null){
					fw.close();			// ファイルクローズ
				}
				if(fr != null){
					fr.close();			// ファイルクローズ
				}
			}catch(IOException e){

			}				//例外処理
		}
	}

}
実行結果
あいうえお
かきくけこ

同じファイル(File2.txt)に書き込みながら読み込むという処理をしています。「あいうえお」「かきくけこ」と書き込んでから、flush()処理を行い(15行目)、その後「さしすせそ」の書き込みを行ってから、ファイルの読み込み(18行目~20行目)をしています。

その結果、画面には、flush()の前に書き込まれた「あいうえお」「かきくけこ」だけが表示されています。しかし、最終的にファイルには、全ての文字が書き込みされています。(図1-2.)

図1-2.File2.txtの中身

File2.txtの中身

このことから、flush()により、FileWriterでは、途中で書き込み内容をファイルに書き込むことが分かります。