OutputStream を InputStream に変換するにはどうすればいいですか? 質問する

OutputStream を InputStream に変換するにはどうすればいいですか? 質問する

私は現在、2 つのモジュールを開発段階に持っています。1 つは として出力されOutputStream、もう 1 つは のみを受け入れますInputStream

これら 2 つの部分を接続できるように、どのようOutputStreamに変換するか (その逆ではなく、実際にこの方法を意味します) をご存知ですか?InputStream

ベストアンサー1

リンクやその他のものはたくさんあるようですが、パイプを使用する実際のコードはありません。java.io.PipedInputStreamそしてjava.io.PipedOutputStreamメモリの追加消費がないことです。ByteArrayOutputStream.toByteArray()は元のバッファのコピーを返すので、メモリ内にあるものはすべて 2 つのコピーを持つことになります。 次に、に書き込むと、InputStreamデータのコピーが 3 つあることになります。

使用したコードlambdas(コメントの @John Manko 氏に感謝):

PipedInputStream in = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(in);
// in a background thread, write the given output stream to the
// PipedOutputStream for consumption
new Thread(() -> {originalOutputStream.writeTo(out);}).start();

@John Manko が指摘したことの 1 つは、特定のケースでは、 OutputStreamの作成を制御できない場合、作成者がOutputStreamオブジェクトを途中でクリーンアップしてしまう可能性があるということです。 を取得している場合はClosedPipeException、コンストラクターを反転してみてください。

PipedInputStream in = new PipedInputStream(out);
new Thread(() -> {originalOutputStream.writeTo(out);}).start();

以下の例でもコンストラクターを反転できることに注意してください。

Threadを単に開始するのではなく、を開始するように訂正してくれた @AlexK にも感謝しますRunnable


使用するコードtry-with-resources:

// take the copy of the stream and re-write it to an InputStream
PipedInputStream in = new PipedInputStream();
    new Thread(new Runnable() {
        public void run () {
            // try-with-resources here
            // putting the try block outside the Thread will cause the
            // PipedOutputStream resource to close before the Runnable finishes
            try (final PipedOutputStream out = new PipedOutputStream(in)) {
                // write the original OutputStream to the PipedOutputStream
                // note that in order for the below method to work, you need
                // to ensure that the data has finished writing to the
                // ByteArrayOutputStream
                originalByteArrayOutputStream.writeTo(out);
            }
            catch (IOException e) {
                // logging and exception handling should go here
            }
        }
    }).start();

私が書いた元のコード:

// take the copy of the stream and re-write it to an InputStream
PipedInputStream in = new PipedInputStream();
final PipedOutputStream out = new PipedOutputStream(in);
new Thread(new Runnable() {
    public void run () {
        try {
            // write the original OutputStream to the PipedOutputStream
            // note that in order for the below method to work, you need
            // to ensure that the data has finished writing to the
            // ByteArrayOutputStream
            originalByteArrayOutputStream.writeTo(out);
        }
        catch (IOException e) {
            // logging and exception handling should go here
        }
        finally {
            // close the PipedOutputStream here because we're done writing data
            // once this thread has completed its run
            if (out != null) {
                // close the PipedOutputStream cleanly
                out.close();
            }
        }   
    }
}).start();

このコードでは、ファイルに書き込む場合を除き、通常はこれが唯一使用可能な出力ストリームであると想定していますoriginalByteArrayOutputStream ByteArrayOutputStreamこれの優れた点は、別のスレッドにあるため、並列で動作し、入力ストリームを消費しているものはすべて、古い出力ストリームからもストリーミングされることです。これは、バッファを小さく保つことができ、レイテンシとメモリ使用量が少なくなるため、有益です。

がない場合はByteArrayOutputStream、 を使用する代わりに、 クラスのメソッドの 1 つ、またはサブクラスで使用可能な他のメソッドの 1 つwriteTo()を使用する必要があります。write()java.io.OutputStream

おすすめ記事