19
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Java] ファイル書き込みは何を使えばいいのか

Last updated at Posted at 2018-10-23

背景

ファイル読み書きってたくさんクラスがあるが、何クラスを使用するのがベストなのか分かっていませんでした。
昔は、別プロジェクトでのコードを コピペ 参考にしていました。
なので、調べてみました。
結論から言うと、調べれば調べるほど混乱しました。
そして、これを使えばいい!!というものが見つかったわけでもありません。

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日くらいかけて、調べてみたのですが、大まかには理解できました。
ただ、詳細が理解できていないなと感じています。
もし、間違っている、もしくはこのコードは無駄では?という箇所があったらご指摘いただけたらと思います。

19
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?