質問

このページ: http://blog.ostermiller.org/convert-java-outputstream -inputstream OutputStreamからInputStreamを作成する方法について説明します:

new ByteArrayInputStream(out.toByteArray())

他の代替手段は、PipedStreamsと新しいスレッドを使用することです。これは面倒です。

私は、多くのメガバイトをメモリ内の新しいバイト配列にコピーするという考えが好きではありません。 これをより効率的に行うライブラリはありますか?

編集:

Laurence Gonsalvesからのアドバイスにより、私はPipedStreamsを試しましたが、対処するのはそれほど難しくありませんでした。 clojureのサンプルコードは次のとおりです。

(defn #^PipedInputStream create-pdf-stream [pdf-info]
  (let [in-stream (new PipedInputStream)
        out-stream (PipedOutputStream. in-stream)]
    (.start (Thread. #(;Here you write into out-stream)))
    in-stream))
役に立ちましたか?

解決

すべてのデータを一度にメモリ内バッファにコピーしたくない場合は、OutputStream(プロデューサー)を使用するコードとInputStreamを使用するコードが必要になります。 (コンシューマ)は、同じスレッドで交互に動作するか、2つの別々のスレッドで同時に動作します。それらを同じスレッドで動作させることは、おそらく2つの別々のスレッドを使用するよりもはるかに複雑であり、エラーが発生しやすくなります実質的にデッドロック)、プロデューサーとコンシューマーを同じループで実行する必要があります。

2番目のスレッドを使用します。それほど複雑ではありません。リンク先のページには完璧な例がありました:

  PipedInputStream in = new PipedInputStream();
  PipedOutputStream out = new PipedOutputStream(in);
  new Thread(
    new Runnable(){
      public void run(){
        class1.putDataOnOutputStream(out);
      }
    }
  ).start();
  class2.processDataFromInputStream(in);

他のヒント

EasyStream という別のオープンソースライブラリがあります。 >パイプとスレッドを透過的に処理します。 すべてがうまくいけば、それは本当に複雑ではありません。問題が発生する場合(ローレンスゴンサルベスの例を見て)

  

class1.putDataOnOutputStream(out);

例外をスローします。 その例では、スレッドは単純に完了し、例外は失われますが、外側の InputStream は切り捨てられる場合があります。

Easystreamは、例外の伝播や、私が約1年間デバッグしてきたその他の厄介な問題を扱っています。 (私は図書館の管理人です:明らかに私の解決策は最高の解決策です;)) 使用方法の例を次に示します。

final InputStreamFromOutputStream<String> isos = new InputStreamFromOutputStream<String>(){
 @Override
 public String produce(final OutputStream dataSink) throws Exception {
   /*
    * call your application function who produces the data here
    * WARNING: we're in another thread here, so this method shouldn't 
    * write any class field or make assumptions on the state of the outer class. 
    */
   return produceMydata(dataSink)
 }
};

また、素敵な紹介があり、他のすべての方法でOutputStreamを変換しますInputStreamへの入力について説明します。見る価値はあります。

バッファのコピーを回避する簡単な解決策は、特別な目的の ByteArrayOutputStream

を作成することです
public class CopyStream extends ByteArrayOutputStream {
    public CopyStream(int size) { super(size); }

    /**
     * Get an input stream based on the contents of this output stream.
     * Do not use the output stream after calling this method.
     * @return an {@link InputStream}
     */
    public InputStream toInputStream() {
        return new ByteArrayInputStream(this.buf, 0, this.count);
    }
}

必要に応じて上記の出力ストリームに書き込み、 toInputStream を呼び出して、基礎となるバッファで入力ストリームを取得します。その時点の後、出力ストリームは閉じていると考えます。

InputStreamをOutputStreamに接続する最良の方法は、次のようにjava.ioパッケージで利用可能な pipedストリームを使用することだと思います:

// 1- Define stream buffer
private static final int PIPE_BUFFER = 2048;

// 2 -Create PipedInputStream with the buffer
public PipedInputStream inPipe = new PipedInputStream(PIPE_BUFFER);

// 3 -Create PipedOutputStream and bound it to the PipedInputStream object
public PipedOutputStream outPipe = new PipedOutputStream(inPipe);

// 4- PipedOutputStream is an OutputStream, So you can write data to it
// in any way suitable to your data. for example:
while (Condition) {
     outPipe.write(mByte);
}

/*Congratulations:D. Step 4 will write data to the PipedOutputStream
which is bound to the PipedInputStream so after filling the buffer
this data is available in the inPipe Object. Start reading it to
clear the buffer to be filled again by the PipedInputStream object.*/

私の意見では、このコードには2つの主な利点があります:

1-バッファ以外のメモリの追加消費はありません。

2-データのキューイングを手動で処理する必要はありません

通常、デッドロックの可能性の増加、コードの理解の難しさ、例外処理の問題のために、別のスレッドの作成を避けようとしています。

私の提案するソリューションは次のとおりです。produceChunk()を繰り返し呼び出すことにより、チャンクでコンテンツを作成するProducerInputStream:

public abstract class ProducerInputStream extends InputStream {

    private ByteArrayInputStream bin = new ByteArrayInputStream(new byte[0]);
    private ByteArrayOutputStream bout = new ByteArrayOutputStream();

    @Override
    public int read() throws IOException {
        int result = bin.read();
        while ((result == -1) && newChunk()) {
            result = bin.read();
        }
        return result;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int result = bin.read(b, off, len);
        while ((result == -1) && newChunk()) {
            result = bin.read(b, off, len);
        }
        return result;
    }

    private boolean newChunk() {
        bout.reset();
        produceChunk(bout);
        bin = new ByteArrayInputStream(bout.toByteArray());
        return (bout.size() > 0);
    }

    public abstract void produceChunk(OutputStream out);

}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top