多くのJava標準ライブラリとサードパーティライブラリがあり、それらのパブリックAPIには、への書き込みまたはからの読み取りのためのメソッドがありますStream
。一例として、処理された画像のコンテンツを書き込むことがありますjavax.imageio.ImageIO.write()
。OutputStream
もう1つの例は、結果のpdfを書き込むためのiTextpdf処理ライブラリです。OutputStream
3番目の例はAmazonS3JavaAPIで、これはInputStream
それを読み取り、S3ストレージにファイルを作成します。
これらの2つを組み合わせたい場合、問題が発生します。たとえば、結果をにプッシュするためBufferedImage
に使用する必要がある画像があります。ただし、S3で必要なため、AmazonS3にプッシュする直接的な方法はありません。
これを解決する方法はいくつかありますが、この質問の主題はの使用法です。ImageIO.write
OutputStream
InputStream
ByteArrayOutputStream
背後にある考え方は、出力ストリームに書き込みたい人が配列に書き込み、読み取りたい人が配列を読み取るように、ByteArrayOutputStream
ラップされた中間バイト配列を使用することです。Input/Output Stream
私の疑問は、たとえば、バイト配列に直接アクセスできるをByteArrayOutputStream
提供するために、バイト配列をコピーせずにバイト配列へのアクセスを許可しない理由です。InputStream
これにアクセスする唯一の方法は、を呼び出すことです。これtoByteArray()
により、内部配列(標準配列)のコピーが作成されます。つまり、私の画像の例では、メモリに画像の3つのコピーがあります。
- 最初は実際の
BufferedImage
、 - 2番目はとの内部
array
ですOutputStream
- 3つ目
toByteArray()
は、を作成できるように作成 されたコピーInputStream
です。
この設計はどのように正当化されますか?
- 実装を隠しますか?を提供するだけ
getInputStream()
で、実装は非表示のままになります。 - マルチスレッド?
ByteArrayOutputStream
とにかく複数のスレッドによるアクセスには適していないので、これはできません。
ByteArrayOutputStream
さらに、 Apacheのcommons-ioライブラリ(内部実装が異なる)によって提供される、の2番目のフレーバーがあります。ただし、どちらもまったく同じパブリックインターフェイスを備えているため、バイト配列をコピーせずにアクセスする方法はありません。