【Java Gold】入出力系のクラスがゴチャりがちなので整理した

「**`Reader` , `InputStreamReader`, `BufferedReader`, `InputStream`, `FileInputStream`, `BufferedInputStream`**」 とか、「**`Writer`, `OutputStreamWriter`, `BufferedWriter`, `OutputStream`, `FileOutputStream`, `BufferedOutputStream`**」
の辺りがゴチャったので整理します。

## 1. 親子関係をみる
```textplain:java.io
java.lang.Object
└── java.io
    ├── InputStream 
    │   ├── FileInputStream
    │   ├── BufferedInputStream
    │   └── DataInputStream
    ├── OutputStream
    │   ├── FileOutputStream
    │   ├── BufferedOutputStream
    │   └── DataOutputStream
    ├── Reader
    │   ├── InputStreamReader
    │   │   └── FileReader
    │   └── BufferedReader
    └── Writer
        ├── OutputStreamWriter
        │   └── FileWriter
        └── BufferedWriter
```

| クラス                  | 説明                                                       |
|------------------------|-----------------------------------------------------------| 
| **`InputStream`**         | **バイトストリーム** の読み取り用抽象クラス。                       |
| **`OutputStream`**        | **バイトストリーム** の書き込み用抽象クラス。                      |
| **`Reader`**              | **文字ストリーム** の読み取り用抽象クラス。                        |
| **`Writer`**             | **文字ストリーム** の書き込み用抽象クラス。                       |

:::note info
扱う形式がバイトストリームなのか、文字ストリームなのかで分かれていますね。
:::

## 2. 読み込み：バイトストリーム系と文字ストリーム系の使い分け

| **判断基準**                 | **`InputStream`（バイトストリーム）**                                    | **`Reader`（文字ストリーム）**                                         |
|-----------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------|
| **扱うデータの種類**         | バイナリデータ（画像、音声、動画など）                                   | テキストデータ（文字列、JSON、XMLなど）                               |
| **エンコーディングの考慮**   | 必要ない（データはそのままバイトとして扱う）                              | 必要（テキストを正しく解釈するため、エンコーディングの指定が必要）        |
| **主な使用例**               | ファイルコピー、ネットワーク通信（バイナリプロトコル）、バイナリファイル操作 | テキストファイルの読み書き、構造化データの処理（例: JSON、HTML、XML）   |
| **データの単位**             | バイト単位（`byte` 型）                                                 | 文字単位（`char` 型、ユニコード文字を扱う）                           |

- **バイナリデータ**（画像、音声、圧縮ファイル）:
  - → `InputStream` 系列を使用。
  - バッファを使って効率化したい場合は `BufferedInputStream` を追加。

- **テキストデータ**（文字列、JSON、XML）:
  - → `Reader` 系列を使用。
  - エンコーディングが必要な場合は `InputStreamReader` を使用。
  - 効率化したい場合は `BufferedReader` を追加。

---
```java:バイナリデータの読み込み①
InputStream input = new FileInputStream("image.png") // 1.バイトストリームとしてデータを取得
```
```java:バイナリデータの読み込み②（バッファの利用あり）
BufferedInputStream input = new BufferedInputStream(// 2.バイトストリームの読み込みにバッファを使う
                                new FileInputStream("example.txt")); // 1.バイトストリームとしてデータを取得
```
* バイトストリームを直接扱う場合、テキストデータではなくバイナリデータ（画像や音声など）が対象。
* **`BufferedInputStream`** は効率的なバイトストリームの読み込みをサポート。

---

```java:テキストデータの読み込み①（エンコード指定なし）
Reader reader = new FileReader("example.txt"); // 1.文字ストリームとしてデータを取得
```
```java:テキストデータの読み込み②（エンコード指定あり）
Reader reader = new InputStreamReader(// 2.バイトストリームを文字ストリームに変換
                    new FileInputStream("example.txt"), "UTF-8")) // 1.バイトストリームとしてデータを取得
```
```java:テキストデータの読み込み③（エンコード指定あり、バッファの利用あり）
BufferedReader reader = new BufferedReader( // 3.文字ストリームの読み込みにバッファを使う
                            new InputStreamReader(// 2.バイトストリームを文字ストリームに変換
                                new FileInputStream("example.txt"), "UTF-8")) // 1.バイトストリームとしてデータを取得
```
* `FileReader`は文字ストリームでデータを直接読み込む、読み込み用の簡易クラスです
* 文字ストリームを直接扱う手段は限定的です
* 基本的に、ファイルはバイト形式でデータを保持しています
* バイト形式のままだと文字化けする可能性があります
* そのため、**基本的には、バイトストリーム⇒文字ストリームの変換が必要**
* **その変換用のクラスが`InputStreamReader`**（`Reader`のサブクラス）
* **`BufferedReader`** は効率的な文字ストリームの読み込みをサポート

:::note info
エンコードを指定したい場合、バイトストリームで読み込み⇒文字ストリームに変換のルートしかありません。
:::

## **3. 書き込み：バイトストリーム系と文字ストリーム系の使い分け**

| **判断基準**                 | **`OutputStream`（バイトストリーム）**                              | **`Writer`（文字ストリーム）**                                      |
|-----------------------------|--------------------------------------------------------------------|-------------------------------------------------------------------|
| **扱うデータの種類**         | バイナリデータ（画像、音声、動画など）                              | テキストデータ（文字列、JSON、XMLなど）                            |
| **エンコーディングの考慮**   | 必要ない（データはそのままバイトとして扱う）                         | 必要（テキストを正しく書き込むため、エンコーディングの指定が必要）   |
| **主な使用例**               | ファイルコピー、ネットワーク通信、バイナリファイル操作               | テキストファイルの生成、構造化データの保存（例: JSON、HTML、XML）   |
| **データの単位**             | バイト単位（`byte` 型）                                            | 文字単位（`char` 型、ユニコード文字を扱う）                        |

- **バイナリデータ**（画像、音声、動画など）:
  - → `OutputStream` 系列を使用。
  - バッファを使って効率化したい場合は `BufferedOutputStream` を追加。

- **テキストデータ**（文字列、JSON、XML）:
  - → `Writer` 系列を使用。
  - エンコーディングが必要な場合は `OutputStreamWriter` を使用。
  - 効率化したい場合は `BufferedWriter` を追加。
---
```java:バイナリデータの書き込み①
OutputStream output = new FileOutputStream("example.bin"); // 1.バイトストリームとしてデータを書き込む
```

```java:バイナリデータの書き込み②（バッファの利用あり）
BufferedOutputStream output = new BufferedOutputStream( // 2.バイトストリームの書き込みにバッファを使う
                                new FileOutputStream("example.bin")); // 1.バイトストリームとしてデータを書き込む
```
- バイトストリームを直接扱う場合、テキストデータではなくバイナリデータ（画像や音声など）が対象。
- **`BufferedOutputStream`** は効率的なバイトストリームの書き込みをサポート。

---

```java:テキストデータの書き込み①
Writer writer = new FileWriter("example.txt"); // 1.文字ストリームとしてデータを書き込む
```
```java:テキストデータの書き込み②（エンコード指定あり）
Writer writer = new OutputStreamWriter( // 2.バイトストリームを文字ストリームに変換
                    new FileOutputStream("example.txt"), "UTF-8"); // 1.バイトストリームとしてデータを書き込む
```
```java:テキストデータの書き込み③（エンコード指定あり、バッファの利用あり）
BufferedWriter writer = new BufferedWriter( // 3.文字ストリームの書き込みにバッファを使う
                            new OutputStreamWriter( // 2.バイトストリームを文字ストリームに変換
                                new FileOutputStream("example.txt"), "UTF-8")); // 1.バイトストリームとしてデータを書き込む
```
* `FileWriter`は文字ストリームでデータを直接書き込む、書き込み用の簡易クラスです
* **`OutputStreamWriter`** はバイトストリーム⇒文字ストリームの変換用クラス
* **`BufferedWriter`** は効率的な文字ストリームの読み込みをサポート
:::note info
エンコードを指定したい場合、バイトストリームで書き込み⇒文字ストリームに変換のルートしかありません。
:::


## まとめ

### 読み込み
- **文字ストリーム系**

| **クラス**               | **説明**                                                                                       |
|--------------------------|-----------------------------------------------------------------------------------------------|
| **`Reader`**             | 文字ストリームの読み取りを行うための抽象クラス。                                                |
| **`FileReader`**| ファイルから文字ストリームとしてデータを読み込む簡易クラス（デフォルトエンコーディング使用）|
| **`InputStreamReader`**  | バイトストリームを文字ストリームに変換するためのラッパークラス。                                |
| **`BufferedReader`**     | 文字ストリームの読み取りを効率化するためのバッファリングクラス。行単位の操作（`readLine()`）も可能。 |

- **バイトストリーム系**

| **クラス**               | **説明**                                                                                       |
|--------------------------|-----------------------------------------------------------------------------------------------|
| **`InputStream`**        | バイトストリームの読み取りを行うための抽象クラス。                                              |
| **`FileInputStream`**| ファイルからバイトストリームとしてデータを読み込むクラス|
| **`BufferedInputStream`**| バイトストリームの読み取りを効率化するためのバッファリングクラス。                               |

---

### 書き込み
- **文字ストリーム系**

| **クラス**| **説明**|
|----------|--------|
| **`Writer`**| 文字ストリームの書き込みを行うための抽象クラス。
| **`FileWriter`**| ファイルに文字ストリームとしてデータを書き込む簡易クラス（デフォルトエンコーディング使用）|
| **`OutputStreamWriter`**| バイトストリームを文字ストリームに変換するためのラッパークラス（エンコーディング指定可能）|
| **`BufferedWriter`**| 文字ストリームの書き込みを効率化するためのバッファリングクラス。行単位での操作も可能。

- **バイトストリーム系**

| **クラス**| **説明**|
|----------|--------|
| **`OutputStream`**| バイトストリームの書き込みを行うための抽象クラス。 |
| **`FileOutputStream`**| ファイルにバイトストリームとしてデータを書き込むクラス|
| **`BufferedOutputStream`**| バイトストリームの書き込みを効率化するためのバッファリングクラス。|