4

多くのJava標準ライブラリとサードパーティライブラリがあり、それらのパブリックAPIには、への書き込みまたはからの読み取りのためのメソッドがありますStream。一例として、処理された画像のコンテンツを書き込むことがありますjavax.imageio.ImageIO.write()OutputStreamもう1つの例は、結果のpdfを書き込むためのiTextpdf処理ライブラリです。OutputStream3番目の例はAmazonS3JavaAPIで、これはInputStreamそれを読み取り、S3ストレージにファイルを作成します。

これらの2つを組み合わせたい場合、問題が発生します。たとえば、結果をにプッシュするためBufferedImageに使用する必要がある画像があります。ただし、S3で必要なため、AmazonS3にプッシュする直接的な方法はありません。 これを解決する方法はいくつかありますが、この質問の主題はの使用法です。ImageIO.writeOutputStreamInputStream
ByteArrayOutputStream

背後にある考え方は、出力ストリームに書き込みたい人が配列に書き込み、読み取りたい人が配列を読み取るように、ByteArrayOutputStreamラップされた中間バイト配列を使用することです。Input/Output Stream

私の疑問は、たとえば、バイト配列に直接アクセスできるをByteArrayOutputStream提供するために、バイト配列をコピーせずにバイト配列へのアクセスを許可しない理由です。InputStreamこれにアクセスする唯一の方法は、を呼び出すことです。これtoByteArray()により、内部配列(標準配列)のコピーが作成されます。つまり、私の画像の例では、メモリに画像の3つのコピーがあります。

  • 最初は実際のBufferedImage
  • 2番目はとの内部arrayですOutputStream
  • 3つ目toByteArray()は、を作成できるように作成 されたコピーInputStreamです。

この設計はどのように正当化されますか?

  • 実装を隠しますか?を提供するだけgetInputStream()で、実装は非表示のままになります。
  • マルチスレッド?ByteArrayOutputStreamとにかく複数のスレッドによるアクセスには適していないので、これはできません。

ByteArrayOutputStreamさらに、 Apacheのcommons-ioライブラリ(内部実装が異なる)によって提供される、の2番目のフレーバーがあります。ただし、どちらもまったく同じパブリックインターフェイスを備えているため、バイト配列をコピーせずにアクセスする方法はありません。

4

3 に答える 3

6

私の疑問は、ByteArrayOutputStreamが、バイト配列に直接アクセスできるInputStreamを提供するなど、バイト配列に対処せずにバイト配列へのアクセスを許可しない理由です。

私は4つの理由を考えることができます:

  • 現在の実装では単一のバイト配列を使用していますが、バイト配列のリンクリストとして実装することもでき、アプリケーションが要求するまで最終的な配列の作成を延期します。アプリケーションが実際のバイトバッファを認識​​できる場合、単一の配列である必要があります。

  • ByteArrayOutputStream あなたの理解に反して、スレッドセーフでありマルチスレッドアプリケーションでの使用に適しています。しかし、バイト配列への直接アクセスが提供された場合、他の問題を発生させずにそれをどのように同期できるかを確認することは困難です。

  • アプリケーションは、現在のバッファーの最高水準点がどこにあるか、およびバイト配列が(まだ)ライブバイト配列であるかどうかも知る必要があるため、APIはより複雑にする必要があります。(ByteArrayOutputStream実装では、バイト配列を再割り当てする必要がある場合があります...これにより、アプリケーションは、配列ではなくなっ配列への参照を保持したままになります。)

  • バイト配列を公開すると、アプリケーションが配列の内容を変更できるようになりますが、これは問題になる可能性があります。


この設計はどのように正当化されますか?

デザインは、あなたよりもシンプルなユースケースに合わせて調整されています。Java SEクラスライブラリは、考えられるすべてのユースケースをサポートすることを目的としているわけではありません。ただし、他のユースケースに他のストリームクラスを提供することをあなた(またはサードパーティのライブラリ)が妨げることはありません。


肝心なのは、Sunの設計者がのバイト配列を公開しないことを決定したことByteArrayOutputStreamです。(IMO)あなたが考えを変える可能性は低いです。

(そして、あなたが試してみたいのであれば、これはそれを行うのに適切な場所ではありません。

  • Bugsデータベースを介してRFEを送信してみてください。
  • または、機能を追加するパッチを開発し、関連するチャネルを介してOpenJDKチームに送信します。包括的な単体テストとドキュメントを含めると、チャンスが増えます。)

それほど危険ではないAPI設計を考え出すことができれば、ApacheCommonsIO開発者に議論の正しさを納得させることに成功する可能性があります。

あるいは、内部データ構造を公開する独自の特別な目的のバージョンを実装することを妨げるものは何もありません。コードはGPLされているので、コピーすることができます...コード配布に関する通常のGPL規則に従います。

于 2011-06-13T00:29:45.757 に答える
2

あなたが探している振る舞いはパイプだと思います。ByteArrayOutputStreamは単なるOutputStreamであり、入力/出力ストリームではありません。それはあなたが考えていることのために設計されていませんでした。

于 2011-06-13T00:21:51.413 に答える
2

幸い、内部配列はであるため、コピーせずにprotectedサブクラス化してラップすることができます。ByteArrayInputStream

于 2011-06-13T00:29:53.777 に答える