検索

キーワード


【Java】テキストファイルの読み込みと出力

  • 公開日:2020-11-30 23:57:34
  • 最終更新日:2020-12-01 22:58:42
【Java】テキストファイルの読み込みと出力

当記事では、Javaにおけるテキストファイルの読み書きの方法について説明します。Javaにおけるバイナリファイルの読み書きの方法については、以下の記事を参照してください。

【Java】バイナリファイルの入出力

似たような名前のクラスがいろいろあり、Javaの初学者は戸惑うこともあるかもしれませんが、それぞれのクラスには役割や働きに応じたクラス名が付いていますので、そこを理解できれば使い分けも簡単になると思います。よく起こりがちなエラーへの対処法も含めて、Java Gold SE 11の資格を持つ著者が解説したいと思います。

文字コードという枠組みに沿って書かれた、文字を表すファイルをテキストファイルといい、Javaにおけるテキストファイルの読み書きには文字ストリームという仕組みを扱います。文字コード、文字ストリームについての詳しい解説は、以下の記事を参照してください。

【Java】文字コードの変換

【Java】入出力ストリーム(java.ioパッケージ)

Javaにおけテキストファイルの読み取りには、java.ioパッケージのReaderを継承したクラスを用い、出力にはWriterを継承したクラスを使います。Javaには、テキストファイルを扱う様々なクラスが用意されていますが、当記事では以下のよく使われるクラスについて解説します。

・FileReader / FileWriter

・BufferedReader / BufferedWriter

・PrintWriter

・InputStreamReader / OutputStreamWriter


文字ストリームのメソッド

Javaにおいて文字ストリームを扱う抽象クラスであるReader、Writerには、それぞれいくつかのメソッドが用意されています。


Reader

Readerクラスのメソッドは以下の通りです。Readerを継承したクラスで呼び出すことが出来ます。

メソッド名返り値の型説明
read()int入力ストリームから1文字ずつ読み取ります。ファイルの終わりに達したときは-1を返します。
read(char[] c)int入力ストリームから引数に渡したchar配列cにデータをコピーします。返り値は読み取られた文字数です。ファイルの終わりに達したときは-1を返します。
read(char[] c, int off, int len)int入力ストリームから引数に渡したchar配列cにデータをコピーしますが、読み取り開始インデックスoffを指定し、そこから読み込む文字数lenだけ読み取ります。返り値は読み取られた文字数です。ファイルの終わりに達したときは-1を返します。
close()voidストリームをクローズして、メモリへの割り当てを解除します。


Writer

Writerクラスのメソッドは以下の通りです。Writerを継承したクラスで呼び出すことが出来ます。

メソッド名返り値の型説明
write(int c)void
出力ストリームに1文字ずつ書き込みます。char型ではなくint型を引数に渡さなければなりません。
write(char[] c)void出力ストリームに引数に渡したchar配列cを書き込みます。
write(char[] c, int off, int len)void出力ストリームに引数に渡したchar配列cを書き込みますが、書き込みを開始するインデックスoffを指定し、そこから書き込む文字数lenだけ書き込みます。
write(String s)void出力ストリームに引数に渡した文字列sを書き込みます。
write(String s, int off, int len)void出力ストリームに引数に渡した文字列sを書き込みますが、書き込みを開始するインデックスoffを指定し、そこから書き込む文字数lenだけ書き込みます。
flush()voidバッファに格納されている全ての出力文字ストリームを強制的に書き込みます。
close()voidストリームをクローズして、メモリへの割り当てを解除します。


テキストファイルの入出力を行う際の注意点

処理が終わった後に必ずclose()メソッドを実行する

Javaにおいて入出力ストリームのインスタンスを扱う際は、処理が終わった後に必ずclose()メソッドを実行して下さい。これを忘れると、使わないストリームにメモリが割り当てらたままになるメモリリークと呼ばれる状態になり、処理が遅くなるなどの不具合の原因となることがあります。

当記事では、サンプルコードにtry-with-resources構文を用いて処理が終わった後に自動的にclose()メソッドを実行するようにしています。そのため、try-with-resources構文について理解に不安がある方は以下の記事を参照してください。

【Java】try - with - resources 構文


例外:FileNotFoundExceptionについて

よくあるエラーとして、「FileNotFoundException」という例外が起こることがあります。これはJavaにおいてファイルのパスの場所を間違えて指定した場合などに起きます。パスは絶対パスと相対パスの2種類の表記法がありますが、慣れないうちは絶対パスで指定すると間違いが少なくなります。


絶対パスの簡単な取得方法

ファイルの絶対パスを正確かつ簡単に取得したいときは、指定したいファイルのあるフォルダで、上部のバーを右クリックして「アドレスをテキストとしてコピー」という項目を選択して絶対パスをコピーします。

ファイルの絶対パスのテキストをコピーする方法

例えば、上記の画面で操作を行った場合、「C:\JavaWorkspace\Works」というディレクトリの絶対パスがコピーされますが、「\」はエスケープ文字を表す文字なので、Javaに「\」を認識させたい場合は「\」を「\\」と入力する必要があります。例えば、Worksディレクトリ内の「sample.jpg」の絶対パスを指定したい場合は、C:\\JavaWorkspace\\Works\\sample.jpg」とする必要があります。Eclipse上では、文字列を表す「""」のダブルクォーテーションの間にコピーすれば自動的に「\」が「\\」に変換されます。


Cドライブの残り容量にも注意

また、サンプルコードを実行したとき、「error='ページング ファイルが小さすぎるため、この操作を完了できません。' (DOS error/errno=1455)」というエラーメッセージが表示されることがあります。これは、Cドライブの空き容量が足りないために起こるので、十分な空き容量を確保してからコードを実行するようにしてください。


FileReader / FileWriter

FileReader

FileReaderは、ファイルから文字ストリームを作成するためのクラスです。

コンストラクタの引数にはパスを表す文字列、またはFileオブジェクトを取ります。

//コンストラクタに読み取るファイルのパスを表す文字列を渡します。絶対パスでも相対パスでも大丈夫です。
FileReader fr = new FileReader("ファイルのパス");
		
//コンストラクタにFileオブジェクトを指定することも出来ます。
File file = new File("ファイルのパス");
FileReader fr = new FileReader(file);


FileWriter

FileWriterは、ファイルに書き込みを行うための文字出力ストリームを作成するクラスです。FileReader同様、コンストラクタの引数にはファイルのパス名またはFileオブジェクトを取りますが、第二引数に「true」を指定することで追記を行うことも出来ます。

コンストラクタの引数にはパスを表す文字列、またはFileオブジェクトを取ります。

//コンストラクタに読み取るファイルのパスを表す文字列を渡します。絶対パスでも相対パスでも大丈夫です。
FileWriter fw = new FileWriter("ファイルのパス");
				
//FileWriterはデフォルトでは指定したファイルの内容をすべて書き換えますが、
//コンストラクタに2つ目の引数としてtrueを渡すと追記するように指定が出来ます。
FileWriter fw = new FileWriter("ファイルのパス", true);

//コンストラクタにFileオブジェクトを指定することも出来ます。
File file = new File("ファイルのパス");
FileWriter fw = new FileWriter(file);
		
//こちらも2つ目の引数としてtrueを渡すと追記するように指定が出来ます。
FileWriter fw = new FileWriter(file, true);


FileReader / FileWriterの実行例

以下のテキストファイル「HelloWorld.txt」を例に、FileReader / FileWriterを使った、Javaにおけるテキストファイルの読み込みと出力についての解説を行います。

Hello, World!

メモ帳などのワードエディタで上記内容を入力し、HelloWorld.txt」という名前で保存したテキストファイルを用意します。


FileReader / FileWriterのサンプルコード

import java.io.FileReader;
import java.io.FileWriter;

public class FileRWSample {
	public static void main(String[] args) {
		//try-with-resouses構文を使って、処理が終わった後に自動的にclose()メソッドを呼び出すようにします。
		//「;」を使うことで、リソースを複数指定できます。
		//読み込むファイルにHelloWorld.txt、書き出すファイル名にsample.txtを指定しています。
		try (FileReader fr = new FileReader(".\\HelloWorld.txt");
				FileWriter fw = new FileWriter(".\\sample.txt")) {

			//read()メソッドの返り値を格納する変数を宣言します。
			//read()メソッドの戻り値はint型なので、int型の変数を宣言します。
			int chr;

			//read()メソッドは読み取った文字をint型に変換して返し、ファイルの終わりに達した場合は-1を返します。
			//そのため、fr.read()が-1を返すまでwhileループさせるとファイル全体を読み込むことができます。
			while ((chr = fr.read()) != -1) {

				//読み取った文字をコンソールに出力してみます。
				//chrはint型の変数なので、char型にキャストすることで文字に直すことができます。
				System.out.println((char) chr);

				//読み取った文字をsample.txtに書き込みます。
				fw.write(chr);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


FileReader / FileWriterのサンプルコードの実行結果

FileWriterのコンストラクタに渡したパスに「sample.txt」というファイルが生成されます。実際に内容を確認すると、下記のようになっています。

Hello, World!

また、コンソールには以下のように出力されています。

H
e
l
l
o
,
 
W
o
r
l
d
!

文字ストリームから1文字ずつ読み込んでいることが確認できます。


BufferedReader / BufferedWriter

BufferedReader

BufferedReaderは、入力文字ストリームにバッファリング(バッファを利用した読み書きの効率化)の機能を追加するためのクラスです。バッファについては以下の記事で説明しています。

【Java】入出力ストリーム(java.ioパッケージ)

コンストラクタの引数には、Readerクラスを継承したクラス(FileReaderクラスなど)を取ります。

//コンストラクタにReaderクラスのサブクラスを渡します。
FileReader fr =new FileReader("ファイルのパス");
BufferedReader br = new BufferedReader(fr);

また、BufferedReaderには、行をまとめて読み込むためのreadLine()メソッドが追加されています。

メソッド名返り値の型説明
readLine()String入力文字ストリームから1行ずつ読み取ります。終端に達した場合はnullを返します。

BufferedWriter

BufferedWriterは、出力文字ストリームにバッファリングの機能を追加するためのクラスです。

コンストラクタの引数には、Writerクラスを継承したクラス(FileWriterクラスなど)を取ります。

//コンストラクタにWriterクラスのサブクラスを渡します。
FileWriter fw =new FileWriter("ファイルのパス");
BufferedWriter bw = new BufferedWriter(fr);

また、BufferedWriterには、改行文字を書き込むためのnewLine()メソッドが追加されています。

メソッド名返り値の型説明
newLine()void出力文字ストリームに改行文字を書き込みます。


BufferedReader / BufferedWriterの実行例

以下のテキストファイル「IAmACat.txt」を例に、BufferedReader / BufferedWriterを使ったテキストファイルの読み込みと出力についての解説を行います。

吾輩は猫である。
名前はまだ無い。
どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。

メモ帳などのワードエディタで上記内容を入力し、IAmACat.txt」という名前で保存したテキストファイルを用意します。


BufferedReader / BufferedWriterのサンプルコード

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;

public class BufferedRWsample {
	public static void main(String[] args) {
		//読み込むファイルにIAmACat.txt、書き出すファイル名にsample2.txtを指定しています。
		try (BufferedReader br = new BufferedReader(new FileReader(".\\IAmACat.txt"));
				BufferedWriter bw = new BufferedWriter(new FileWriter(".\\Sample2.txt"))) {

			//文字ストリームのテキスト行を格納するためのString型の変数lineを宣言します。
			String line;

			//readLine()メソッドは文字ストリームから1行ずつ読み込むことが出来ますが、
			//終端に達したときにnullを返します。
			//そのため、linebr.readLine()がnullを返すまでwhileループさせるとファイル全体を読み込むことが出来ます。
			while ((line = br.readLine()) != null) {

				//文字ストリームから読み込んだ内容を出力します。
				System.out.println(line);

				//読み込んだ内容を書き込みます。改行文字はreadLine()メソッドでは読み取らないので、
				//改行を出力したい場合はnewLine()メソッドを使う必要があります。
				bw.write(line);
				bw.newLine();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


BufferedReader / BufferedWriterのサンプルコードの実行結果

FileWriterのコンストラクタに渡したパスに新たに「sample2.txt」が出力されてことが確認できます。実際に「sample2.txt」の内容を確認すると、「IAmACat.txt」と同じ内容になっていることが確認できます。

また、コンソールには以下のように「IAmACat.txt」と同じ内容が出力されます。

吾輩は猫である。
名前はまだ無い。
どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。


テキストファイルに追記するには

BufferedReader / BufferedWriterで使った「sample2.txt」を例に、Javaにおいてテキストファイルに追記する方法について説明します。


テキストファイルに追記するサンプルコード

以下のコードで、「sample2.txt」に新たな行を追加します。

import java.io.BufferedWriter;
import java.io.FileWriter;

public class BufferedWriterAppendSample {
	public static void main(String[] args) {
		//FileWriterの第2引数にtrueを渡すことで、追記を行います。
		try (BufferedWriter bw = new BufferedWriter(new FileWriter(".\\sample2.txt", true))) {

			//追記する内容を記述します。改行を行うには、newLine()メソッドを使います。
			bw.write("吾輩はここで始めて人間というものを見た。");
			bw.newLine();
			bw.write("しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。");
			bw.newLine();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


テキストファイルに追記するサンプルコードの実行結果

このコードを実行した後に、「sample2.txt」の内容を確認すると、以下のような内容になっています。

吾輩は猫である。
名前はまだ無い。
どこで生れたかとんと見当がつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。
しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。

sample2.txtに2行の文章が追加されたことが確認できます。


PrintWriter

PrintWriterは、Java上でテキストファイルを出力する時に便利な、様々なメソッドを用意したクラスにです。

コンストラクタには、Writerを継承したクラスの他にも、OutputStreamを継承したクラスやFileクラス、パス名を表す文字列を渡すことが出来ます。

また、第二引数に文字コードを表す文字列を入れることで、文字コードの指定が出来ます。文字コードについては、以下の記事で解説しています。

【Java】文字コードの変換

//コンストラクタにWriteクラスのサブクラスを渡します。
FileWriter fw = new FileWriter("ファイルのパス");
PrintWriter pw = new PrintWriter(fw);

//コンストラクタにOutputStreamクラスのサブクラスを渡すことも出来ます。
FileOutputStream fos = new FileOutputStream("ファイルのパス");
PrintWriter pw = new PrintWriter(fos);

//コンストラクタに書き込むファイルのパスを直接指定することも出来ます。
PrintWriter pw = new PrintWriter("ファイルのパス");

//コンストラクタにFileオブジェクトを指定することも出来ます。
File file = new File("ファイルのパス");
PrintWriter pw = new PrintWriter(file);

//コンストラクタに文字コードを指定することで、書き込む際の文字コードを変更することが出来ます。
//WriterクラスやOutputStreamクラスを継承したクラスを渡したときは、
//文字コードは指定できませんので注意してください。
PrintWriter pw = new PrintWriter("ファイルのパス", "Unicode");


また、PrintWriterには、以下のようなメソッドが追加されています。

メソッド名返り値の型説明
print(String s)void出力ストリームに引数に渡した文字列sを書き込みます。
println(String s)void出力ストリームに引数に渡した文字列sを書き込みます。最後に行の区切り文字を出力して、改行を行います。
printf(String format, Object... args)PrintWriter書式指定子を含む文字列formatと、書式を指定して出力を行う、任意のオブジェクトからなる可変長引数argsを渡して指定した書式で書き込みます。

上記のうち、printメソッドとprintlnメソッドの引数には、String型の他に、int型やboolean型などのプリミティブ型、さらにはObject型を渡すことが出来ます。

printfメソッドは、System.out.printfメソッドと同様の書式指定子を使いますので、書式指定子に関する詳しい説明については、以下の記事を参照してください。

【Java】標準入出力とScannerクラスの使い方


PrintWriterの実行例

PrintWriterに用意された様々なメソッドを使って、テキストファイルに書き込みを行う方法を説明します。


PrintWriterのサンプルコード

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Date;

public class PrintWriterSample {
	public static void main(String[] args) {
		//PrintWriterのコンストラクタにBufferedWriterを渡すことで、書き込み時にバッファを利用できます。
		try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(".\\sample4.txt")))){

			//改行せずに文字列を書き込みます。
			pw.print("Hello, ");

			//改行して文字列を書き込みます。
			pw.println("World!");
			
			//boolean型やint型なども、変換を行うことなく直接書き込みを行うことが出来ます。
			pw.println(true);
			pw.println(123);

			//書式指定子を使って、変数を文字列に含んだ状態で書き込みを行います。
			//ここでは、%sに「25」が代入されます。
			pw.printf("私の年齢は %s 才です。", 25);
			pw.println();

			//書式指定子を使って、浮動小数点の書き込み形式を指定します。
			//ここでは、小数点以下第7桁を四捨五入して書き込みます。
			double pi = 3.14159265;
			pw.printf("円周率は %e です。", pi);
			pw.println();

			//書式指定子を使って、日時の書き込み形式を指定します。
			//ここでは、Date()メソッドで現在の日時を取得して書き込みを行っています。
			Date c = new Date();
			pw.printf("現在の日時は %tY年 %tm月 %td日 %tH時 %tM分 %tS秒 です。", c, c, c, c, c, c);
			pw.println();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

try-with-resources構文中のリソースが複雑なように感じますが、動作の中身としてはFileWriterクラスにBufferedWriterクラスのバッファリング機能を付け、さらにPrintWriterクラスの機能を付けるという構造になっています。ファイル出力の基本となるFileWriterクラスに、機能を追加していくイメージで考えればわかりやすいと思います。


PrintWriterのサンプルコードの実行結果

このコードを実行した後に、「sample3.txt」の内容を確認すると、以下のような内容になっています。

Hello, World!
true
123
私の年齢は 25 才です。
円周率は 3.141593e+00 です。
現在の日時は 2020年 11月 26日 16時 33分 44秒 です。

PrintWriterのメソッドを使って様々な書式で出力が出来ることが確認できます。


InputStreamReader / OutputStreamWriter

InputStreamReader / OutputStreamWriterは、それぞれInputStreamからReader、OutputStreamからWriterの橋渡しをするためのクラスで、バイトストリームを文字ストリームに変換します。主にJava上でテキストファイルの文字コードを変換する際などに使われます。

InputStreamReader / OutputStreamWriterの使用例については、以下の記事で掲載しています。

【Java】文字コードの変換


InputStreamReader

inputStreamWriterは、指定した文字コードでバイトストリームから入力文字ストリームを読み込むためのクラスです。

コンストラクタの第一引数には、InputStreamクラスを継承したクラス(FileInputStreamクラスなど)を取り、第二引数には文字コードを表す文字列を取ります。

//コンストラクタの第一引数にInputStreamクラスのサブクラス、第二引数に文字コードを表す文字列渡します。
//第二引数を省略した場合は、デフォルトの文字コードを使用した入力文字ストリームを作成します。
FileInputStream fis =new FileInputStream("ファイルのパス");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");


OutputStreamWriter

OutputStreamWriterは、指定した文字コードでバイトストリームから出力文字ストリームを書き出すためのクラスです。

コンストラクタの引数には、OutputStreamクラスを継承したクラス(FileOutputStreamクラスなど)を取り、第二引数には文字コードを表す文字列を取ります。

//コンストラクタの第一引数にOutputStreamクラスのサブクラス、第二引数に文字コードを表す文字列渡します。
//第二引数を省略した場合は、デフォルトの文字コードを使用した出力文字ストリームを作成します。
FileOutputStream fos =new FileOutputStream("ファイルのパス");
OutputStreamReader osr = new OutputStreamReader(fos, "UTF-8");


まとめ

今回はJavaにおけるテキストファイルの読み込みと出力についての説明を行いました。様々なクラスがありますが、FileReader/FileWriterを基本として、それを拡張するという考え方をすればわかりやすいと思います。Javaを扱う実務でもログファイルの出力など、頻繁に使う機会があるので、その際に当記事が参考になれば幸いです。


関連記事:

【Java】try - with - resources 構文

【Java】標準入出力とScannerクラスの使い方

【Java】入出力ストリーム(java.ioパッケージ)

【Java】バイナリファイルの入出力

【Java】文字コードの変換


【著者】

ゆうさい

フォワードソフト株式会社のエンジニア。経験はまだ浅いものの、Java、Python、JavaScriptなど様々な言語の他、クラウドやネットワーク技術を勉強しています。PythonやVBAを使った自動化で楽をするのを考えるのが好きです。 Oracle Certified Java Programmer Gold SE 11、HTML5プロフェッショナル認定試験レベル2、AWSプラクティショナーなどの情報資格を保有しています。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様