背景
ファイル読み書きってたくさんクラスがあるが、何クラスを使用するのがベストなのか分かっていませんでした。
昔は、別プロジェクトでのコードを コピペ 参考にしていました。
なので、調べてみました。
結論から言うと、調べれば調べるほど混乱しました。
そして、これを使えばいい!!というものが見つかったわけでもありません。
Streamってなに?
データをバイト単位で処理する。
ちなみに、Streamというクラスは存在しない。
インターフェース
https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html
InputStream
バイトで**「read」**を行うクラス。
OutputStream
バイトで**「write」**を行うクラス。
FileInputStream
バイトを読み込むためのクラス。
InputStreamの子クラス。
だいぶ古い。
FileOutputStream
バイトを書き込むためのクラス。
OutputStreamの子クラス。
だいぶ古い。
InputStreamReader
InputStreamをReaderに渡す役割。
ここで文字コードを指定する。
OutputStreamWriter
OutputStreamをWriterに渡す役割。
ここで文字コードを指定する。
Reader
ストリームからバイトではなく、文字単位(コードで言うとchar[])で**「read」**を行う。
Writer
ストリームからバイトではなく、文字単位(コードで言うとchar[])で**「write」**を行う。
バッファリングってなに?
メモリにためこんで、一定量たまったら一気に読み書きする機能のこと。
これにより、1バイトずつ読み書きするパフォーマンスが良い。
BufferedReader
Readerのバッファリング機能つき
BufferedWriter
Writerのバッファリング機能つき
ファイル書き込み機能を実装してみた
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileCreate {
public static void main(String[] args) {
// 読み書きするファイルパス
Path path = Paths.get("C:\\demo.txt");
// 書き込む文字列
List<String> lines = Stream.of("あいうえお", "かきくけこ", "さしすせそ").collect(Collectors.toList());
// ファイル書き込み1
// 文字コードはデフォルトでUTF-8
// OutputStreamWriterを使用している
try (BufferedWriter writer = Files.newBufferedWriter(path)) {
for (String str : lines) {
// nullを渡すと、nullという文字列として書き込むようので注意
writer.append(str);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
// ファイル書き込み2
// 内部的にはBufferedWriterとOutputWriter、FileOutputStreamを使用している
try {
// 新規で書き込みたいとき
Files.write(path, lines, Charset.forName("Shift_JIS"), StandardOpenOption.WRITE);
// 追記したいとき
Files.write(path, lines, Charset.forName("Shift_JIS"), StandardOpenOption.APPEND);
} catch (IOException e) {
e.printStackTrace();
}
// ファイル書き込み3
// printWriter
try (
// 追記したいときはtrue、新規のときはfalse
FileOutputStream fileOutputStream = new FileOutputStream(path.toFile(), true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, Charset.forName("Shift_JIS"));
PrintWriter printWriter = new PrintWriter(outputStreamWriter)) {
for (String s : lines) {
printWriter.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
// ファイル書き込み4
// BufferedWriter
try (
// 追記したいときはtrue、新規のときはfalse
FileOutputStream fileOutputStream = new FileOutputStream(path.toFile(), true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, Charset.forName("Shift_JIS"));
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) {
for (String s : lines) {
bufferedWriter.append(s);
bufferedWriter.newLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
簡潔に済ませるのならば、ファイル書き込み1か2で良いかと思います。
ただ、何かと自分好みに書き込み内容をカスタマイズしたいならば、ファイル書き込み3か4を使用しようと思います。
ファイル書き込み3と4は、自分に分かりやすく、ひとつひとつ変数宣言しています。
1行にまとめるのも、もちろんOKです。
new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path.toFile(), true), Charset.forName("Shift_JIS")));
注意すべき点は、close()を忘れないことです。
終わりに
2日くらいかけて、調べてみたのですが、大まかには理解できました。
ただ、詳細が理解できていないなと感じています。
もし、間違っている、もしくはこのコードは無駄では?という箇所があったらご指摘いただけたらと思います。