1. 概要

このチュートリアルでは、JavaクラスOutputStreamの詳細について説明します。 O utputStreamは抽象クラスです。 これは、バイトの出力ストリームを表すすべてのクラスのスーパークラスとして機能します。

「出力」や「ストリーム」などのこれらの単語が何を意味するのかを詳しく調べていきます。

2. JavaIOの簡単な紹介

OutputStreamは、JavaでI/O操作を実行するために必要なクラスを定義するJavaIOAPIの一部です。 これらはすべてjava.io名前空間にパッケージ化されています。 これは、バージョン1.0以降のJavaで使用可能なコアパッケージの1つです。

Java 1.4以降では、名前空間 java.nioにJavaNIOがパッケージ化されており、ノンブロッキングの入出力操作が可能になります。 ただし、この記事の焦点となる領域は、JavaIOの一部としてのObjectStreamです。

JavaIOおよびJavaNIOに関連する詳細は、ここにあります。

2.1. 入出力

Java IOは基本的に、ソースからデータを読み取り、宛先にデータを書き込むメカニズムを提供します。 ここでは、入力はソースを表し、出力は宛先を表します。

これらのソースと宛先は、ファイル、パイプからネットワーク接続まで、何でもかまいません。

2.2. ストリーム

Java IOは、基本的にデータの連続フローを表すストリームの概念を提供します。 ストリームは、バイト、文字、オブジェクトなど、さまざまな種類のデータをサポートできます。

さらに、ソースまたは宛先への接続は、ストリームが表すものです。 したがって、これらはそれぞれInputStreamまたはOutputStreamとして提供されます。

3. OutputStreamのインターフェース

OutputStream は、そのサブクラスにいくつかの明確な特性を提供する一連のインターフェースを実装します。 それらをすばやく調べてみましょう。

3.1. クローズ可能

インターフェイスCloseableは、 close()と呼ばれるメソッドを提供します。このメソッドは、がデータのソースまたは宛先のクローズを処理します。 OutputStreamのすべての実装はこのメソッドの実装を提供します。 ここで、リソースを解放するためのアクションを実行できます。

3.2. AutoCloseable

インターフェイスAutoCloseableは、 close()と呼ばれるメソッドも提供し、Closeableのメソッドと同様の動作をします。 ただし、この場合、メソッドclose()は、try-with-resourceブロックを終了するときに自動的に呼び出されます。

try-with-resourceの詳細については、こちらをご覧ください。

3.3. フラッシュ可能

インターフェイスFlushableは、宛先へのデータのフラッシュを処理する flush()と呼ばれるメソッドを提供します。

OutputStream の特定の実装では、以前に書き込まれたバイトをバッファリングして最適化することを選択できますが、 flush()を呼び出すと、すぐに宛先に書き込まれます

4. OutputStreamのメソッド

OutputStream にはいくつかのメソッドがあり、各実装クラスはそれぞれのデータ型に対して実装する必要があります。

これらは、 CloseableおよびFlushableインターフェースから継承するclose()および flush()メソッドとは別のものです。

4.1. write(int b)

このメソッドを使用して、特定の1バイトをOutputStreamに書き込むことができます。 引数「int」は4バイトで構成されているため、コントラクトと同様に、最初の下位バイトのみが書き込まれ、残りの3つの上位バイトは無視されます。

public static void fileOutputStreamByteSingle(String file, String data) throws IOException {
    byte[] bytes = data.getBytes();
    try (OutputStream out = new FileOutputStream(file)) {
        out.write(bytes[6]);
    }
}

データを「HelloWorld!」としてこのメソッドを呼び出すと、結果として次のテキストを含むファイルが得られます。

W

ご覧のとおり、これは6番目にインデックス付けされた文字列の7番目の文字です。

4.2. write(byte [] b、int off、int length)

このオーバーロードされたバージョンのwrite()メソッドは、バイト配列のサブシーケンスをOutputStream書き込むためにあります。

「off」によって決定されたオフセットで始まる引数で指定されたバイト配列から「長さ」のバイト数をOutputStream:に書き込むことができます。

public static void fileOutputStreamByteSubSequence(
  String file, String data) throws IOException {
    byte[] bytes = data.getBytes();
    try (OutputStream out = new FileOutputStream(file)) {
        out.write(bytes, 6, 5);
    }
}

以前と同じデータを使用してこのメソッドを呼び出すと、出力ファイルに次のテキストが含まれます。

World

これは、インデックス5から始まり、5文字で構成されるデータのサブストリングです。

4.3. write(byte [] b)

これはwrite()メソッドのさらに別のオーバーロードバージョンであり、OutputStreamへの引数で指定されたバイト配列全体を書き込むことができます。

これは、 write(b、0、b.lengh)の呼び出しと同じ効果があります。

public static void fileOutputStreamByteSequence(String file, String data) throws IOException {
    byte[] bytes = data.getBytes();
    try (OutputStream out = new FileOutputStream(file)) {
        out.write(bytes);
    }
}

同じデータを使用してこのメソッドを呼び出すと、出力ファイルにString全体が含まれます。

Hello World!

5. OutputStreamの直接サブクラス

次に、 OutputStream の直接既知のサブクラスのいくつかについて説明します。これらのサブクラスは、OutputStreamが定義する特定のデータ型を個別に表します。

OutputStream から継承されたメソッドを実装する以外に、独自のメソッドを定義します。

これらのサブクラスの詳細については説明しません。

5.1. FileOutputStream

名前が示すように、 FileOutputStream は、ファイルにデータを書き込むためのOutputStreamです。 FileOutputStream は、他の OutputStream と同様に、生のバイトのストリームを書き込むことができます。

前のセクションの一部として、FileOutputStreamのさまざまなメソッドをすでに検討しました。

5.2. ByteArrayOutputStream

ByteArrayOutputStream は、バイト配列にデータを書き込むことができるOutputStreamの実装です。 ByteArrayOutputStream がバッファにデータを書き込む間、バッファは成長し続けます。

バッファのデフォルトの初期サイズを32バイトのままにするか、使用可能なコンストラクタの1つを使用して特定のサイズを設定できます。

ここで注意すべき重要なことは、メソッド close()は実質的に効果がないということです。 ByteArrayOutputStream の他のメソッドは、 close()が呼び出された後でも安全に呼び出すことができます。

5.3. FilterOutputStream

OutputStreamは、主にバイトストリームを宛先に書き込みますが、変換する前にデータを変換することもできます。 FilterOutputStream は、特定のデータ変換を実行するすべてのクラスのスーパークラスを表します。 FilterOutputStream は、常に既存のOutputStreamで構築されます。

FilterOutputStream の例には、 BufferedOutputStream CheckedOutputStream CipherOutputStream DataOutputStream DeflaterOutputStream[ X197X]、 DigestOutputStream InflaterOutputStream PrintStream

5.4. ObjectOutputStream

ObjectOutputStream は、Javaオブジェクトのプリミティブデータ型とグラフを宛先に書き込むことができます。 既存のOutputStreamを使用してObjectOutputStreamを構築し、Fileなどの特定の宛先に書き込むことができます。

オブジェクトが宛先に書き込むには、ObjectOutputStreamに対してSerializableを実装する必要があることに注意してください。 Javaシリアル化の詳細については、こちらをご覧ください。

5.5. PipedOutputStream

PipedOutputStream は、通信パイプの作成に役立ちます。 PipedOutputStream は、接続されたPipedInputStreamが読み取ることができるデータを書き込むことができます。

PipedOutputStream は、PipedInputStreamに接続するコンストラクターを備えています。 または、 PipedOutputStreamで提供されているconnect()というメソッドを使用して、後でこれを行うこともできます。

6. OutputStreamバッファリング

入出力操作には通常、ディスクアクセス、ネットワークアクティビティなどの比較的高価な操作が含まれます。 これを頻繁に実行すると、プログラムの効率が低下する可能性があります。

これらのシナリオを処理するために、Javaにデータの「バッファリングされたストリーム」があります。 BufferedOutputStream は、バッファがいっぱいになるか、メソッド flush()が呼び出されたときに、宛先にフラッシュされる頻度が少ない代わりにデータをバッファに書き込みます。

BufferedOutputStream は、前述の FilterOutputStream を拡張し、既存の OutputStream をラップして、宛先に書き込みます。

public static void bufferedOutputStream(
  String file, String ...data) throws IOException {
 
    try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
        for(String s : data) {
            out.write(s.getBytes());
            out.write(" ".getBytes());
        }
    }
}

注意すべき重要な点は、各データ引数に対する write()のすべての呼び出しは、バッファーへの書き込みのみであり、ファイルへの潜在的にコストのかかる呼び出しにはならないということです。

上記の場合、データを「Hello」、「World!」としてこのメソッドを呼び出すと、コードがメソッド[を呼び出すtry-with-resourcesブロックを終了したときにのみ、データがファイルに書き込まれます。 BufferedOutputStreamのX207X]close()。

これにより、次のテキストを含む出力ファイルが作成されます。

Hello World!

7. OutputStreamWriterを使用したテキストの書き込み

前に説明したように、バイトストリームは、テキスト文字の束である可能性のある生データを表します。 これで、文字配列を取得して、バイト配列への変換を自分で実行できます。

byte[] bytes = data.getBytes();

Javaは、このギャップを埋めるための便利なクラスを提供します。 OutputStream の場合、このクラスはOutputStreamWriterです。 OutputStreamWriterはOutputStreamをラップし、目的の宛先に文字を直接書き込むことができます。

オプションで、OutputStreamWriterにエンコード用の文字セットを提供することもできます。

public static void outputStreamWriter(String file, String data) throws IOException {
    try (OutputStream out = new FileOutputStream(file); 
        Writer writer = new OutputStreamWriter(out,"UTF-8")) {
        writer.write(data);
    }
}

ご覧のとおり、FileOutputStreamを使用する前に文字配列からバイト配列への変換を実行する必要はありません。OutputStreamWriterはこれを便利に実行します。[X207X ]

当然のことながら、「Hello World!」などのデータを使用して上記のメソッドを呼び出すと、次のようなテキストを含むファイルになります。

Hello World!

8. 結論

この記事では、Java抽象クラスOutputStreamについて説明しました。 それが実装するインターフェースとそれが提供するメソッドを調べました。

次に、Javaで使用可能なOutputStreamのサブクラスのいくつかについて説明しました。 最後に、バッファリングと文字ストリームについて話しました。

いつものように、例のコードはGitHubから入手できます。