bytearrayoutputStreamのパブリックインターフェイスの設計の正当化?
-
27-10-2019 - |
質問
多くのJava標準およびサードパーティの図書館があり、公開APIには、書くか読む方法があります。 Stream
。一例は次のとおりです javax.imageio.ImageIO.write()
それには必要です OutputStream
処理された画像のコンテンツを書くには。別の例は次のとおりです itext PDF処理ライブラリ OutputStream
結果のPDFを記述します。 3番目の例は、Amazons3 Java APIです InputStream
それはそれを読み、3でファイルを作成します S3ストレージ.
問題は、これらの2つを組み合わせたい場合に動揺します。たとえば、画像があります BufferedImage
私はそれを使わなければなりません ImageIO.write
結果をプッシュします OutputStream
. 。しかし、ノーはありません 直接 S3が必要とするように、それをAmazonS3にプッシュする方法 InputStream
.
これを解決する方法はほとんどありませんが、この質問の主題はの使用です ByteArrayOutputStream
.
背後にあるアイデア ByteArrayOutputStream
包まれた間層BYTEアレイを使用することです Input/Output Stream
出力ストリームに書き込みたい人が配列に書き込み、読みたい人が配列を読むようにします。
私の不思議はなぜです ByteArrayOutputStream
たとえば、コピーすることなくバイト配列へのアクセスを許可しないでください。 InputStream
それはそれに直接アクセスできます。それにアクセスする唯一の方法は、呼び出すことです toByteArray()
, 、それは内部配列(標準の配列)のコピーを作成します。つまり、私の画像の例では、 三 メモリ内の画像のコピー:
- 初め 実際です
BufferedImage
, - 2番目 内部です
array
のOutputStream
と - 三番 によって作成されたコピーです
toByteArray()
だから私は作成することができますInputStream
.
このデザインはどのように正当化されますか?
- 実装を隠す?提供するだけです
getInputStream()
, 、および実装は隠されたままです。 - マルチスレッド?
ByteArrayOutputStream
とにかく複数のスレッドによるアクセスに適していないため、これはできません。
さらに、2番目の風味があります ByteArrayOutputStream
, 、Apache'sによって提供されます Commons-Io ライブラリ(異なる内部実装があります)。しかし、どちらもまったく同じです 公衆 バイト配列をコピーせずにアクセスする方法を提供しないインターフェイス。
解決
幸いなことに、内部配列はです protected
, 、したがって、あなたはそれをサブクラス化し、ラップすることができます ByteArrayInputStream
コピーなしで、その周り。
他のヒント
私の不思議は、たとえば、それに直接アクセスできる入力ストリームを提供するために、それを対処せずにバイト配列にアクセスできない理由です。
私は4つの理由を考えることができます:
現在の実装では、単一のバイト配列を使用しますが、バイト配列のリンクリストとして実装することもでき、アプリケーションが要求されるまで最終配列の作成を延期することもできます。アプリケーションが実際のバイトバッファーを確認できれば、 持ってる 単一の配列になること。
あなたの理解に反して
ByteArrayOutputStream
は 安全にスレッド、そして は マルチスレッドアプリケーションでの使用に適しています。しかし、バイト配列に直接アクセスが提供された場合、他の問題を作成せずにどのように同期することができるかを確認することは困難です。アプリケーションは、現在のバッファーハイウォーターマークがどこにあるか、およびバイト配列が(まだ)ライブバイトアレイであるかどうかを知る必要があるため、APIはより複雑にする必要があります。 (
ByteArrayOutputStream
実装は、バイト配列を再配置する必要がある場合があります...そして、それはもはやないアレイへの参照を保持するアプリケーションを残します 配列。)バイト配列を公開すると、アプリケーションが配列の内容を変更できるようにします。 になり得る 問題があります。
このデザインはどのように正当化されますか?
デザインは、あなたのものよりも単純なユースケースに合わせて調整されています。 Java SEクラスライブラリは、可能なすべてのユースケースをサポートすることを目指していません。しかし、彼らはあなた(またはサードパーティライブラリ)が他のユースケースに他のストリームクラスを提供することを妨げません。
一番下の行は、サンデザイナーがバイト配列を公開しないことを決めたということです ByteArrayOutputStream
, 、そして(IMO)あなたは彼らの心を変えることはほとんどありません。
(そして、もしあなたが試してみたいなら、これはそれをするのに適した場所ではありません。
- バグデータベースを介してRFEを送信してみてください。
- または、機能を追加するパッチを開発し、関連するチャネルを介してOpenJDKチームに送信します。包括的なユニットテストとドキュメントを含めた場合、チャンスを増やします。)
Apache Commons Io開発者に、あまり危険ではないAPIデザインを思い付くことができる限り、より多くの成功を収めることができます。
または、内部データ構造を公開する独自の特別な目的バージョンを実装することを妨げるものはありません。コードはgpl'edであるため、コピーすることができます...コード配布に関する通常のGPLルールの対象となります。
私はあなたが探している行動は パイプ. 。 bytearrayoutputStreamは、出力ストリームであり、入力/出力ストリームではありません。それはあなたが念頭に置いているもののために設計されていませんでした。