今日は、昨日任意で作成したお題をもとに、ファイル読み込み部分を見ていた。
Java(お題)
「ファイル読み込み」の1つだけで色々なやり方があったり、考えなければならないことがあることを知った。
ファイルを読み込み、読み込んだ内容をコンソールに出力する際、
昨日はこんなやり方で実装した。
1. Fileオブジェクト生成
ファイルのパスを引数にFileオブジェクト生成
2. File存在確認
2-1. Fileが存在する場合
2-1-1. FileReaderオブジェクト生成
上記1.を引数にFileReaderオブジェクト生成
2-1-2. ループ処理
上記2-1-1.で生成したFileReaderオブジェクトのreadメソッドを呼んだ結果の戻り値を変数(data)に格納し、変数(data)が-1になるまで下記処理を行う。
char型でキャストした変数(data)をコンソールに出力する。
2-1-3. ファイルクローズ
上記2-1-1.で生成したFileReaderオブジェクトのcloseメソッドを呼び出す。
2-2. Fileが存在しない場合
文字列(ファイルが存在しません)をコンソールに出力する。
Fileオブジェクトを作って、それをもとにFileReaderオブジェクトを作って、
1文字ずつ回して出力しているだけ。
1文字ずつ回すので処理が遅いという問題があるらしい。
細かいところは正直良く分からないが、まとめて処理してみたいなと思い、
ファイルの内容をリスト化して回す方法でやってみた。Java7以降は使えるらしい。
こんな感じ。
Path file = Paths.get(“ファイルのパス”);
try {
List<String> text = Files.readAllLines(file); // UTF-8
List<String> text2 = Files.readAllLines(file, Charset.forName(“MS932”)); // MS932
for (String str1 : text) {
System.out.println(“test1:”+str1);
}
for (String str2 : text2) {
System.out.println(“test1:”+str2);
}
} catch (IOException e) {
e.printStackTrace();
}
コメントアウトとかして動作確認したところ、下記のことがわかった。
・SJISのファイルに対してreadAllLinesメソッドを呼ぶと、java.nio.charset.MalformedInputExceptionが発生し落ちる。
⇒ ファイルの文字コードをUTF-8にしたら解消された。
ただ疑問なのは、もともと落ちていなかったのに、ファイルの文字コードをSJISからUTF-8に変えたときから、readAllLinesメソッドの第二引数にCharset.forName(“MS932”)と指定したコードで落ちるようになったこと。
リファレンス:
forName(String charsetName)
指定された文字セットのCharsetオブジェクトを返します。
|
単純に、指定した文字コードでファイルの読み込みを行いますよってことだと思われるが、だとしたら、もともと文字コード違い(ファイル側はSJIS、指定はMS932)で落ちるのが普通なのではないか、なぜファイルがSJISだと落ちなくて、UTF-8だと落ちるのか?
っと思ったが、Googleで「MS932 SJIS Java」と検索したところ、
どうやらSJISもMS932も仲間っぽい。納得。
SJISのしたにMS932(とか)がいるイメージ。
また、ファイルの読み込みに関して下記のやり方もあるらしい。
・ファイルの内容をStreamで読み込む(Java8以降)
・FileInputStreamを使って読み込む
・FileReaderだけだと1文字単位だが、BufferedReaderと組み合わせて使えば、BufferedReaderのreadLineメソッドを使って行単位で読み込みができる
・ファイルのエンコーディングを指定し読み込む場合は、InputStreamReaderとFileInputStremを組み合わせて読み込む
・ファイルを読み込むためのBufferedReaderを、Files.newBufferedReaderを使って取得する
Java11からは、Files.readStringという、ファイルの内容を一度に読み込んで1つのStringにできるメソッドも登場してるとのこと。
まだまだ奥が深そうなのでしばらくファイル操作についてもっと見て行こうと思う。