Frage

Diese Seite: http://blog.ostermiller.org/convert-java-outputstream -inputstream beschreibt, wie ein Input von Outputstream erstellen:

new ByteArrayInputStream(out.toByteArray())

Weitere Alternativen sind PipedStreams und neue Themen zu verwenden, das mühsam ist.

Ich mag nicht die Idee des Kopierens viele Megabyte an neuen im Speicher Byte-Array. Gibt es eine Bibliothek, die dies tut effizient?

EDIT:

Mit dem Rat von Laurence Gonsalves, habe ich versucht PipedStreams und es stellte sich heraus, dass sie nicht so schwer sind, zu beschäftigen. Hier ist der Beispielcode in 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))
War es hilfreich?

Lösung

Wenn Sie nicht möchten, dass alle Daten in einem in-Speicherpuffer kopieren auf einmal dann sind Sie gehen zu müssen, Ihren Code haben, der die Output verwendet (der Hersteller) und den Code, der die Input verwendet (der Verbraucher) entweder abwechselnd demselben Thread oder gleichzeitig in zwei getrennten Threads arbeiten. sie arbeiten in dem gleichen Thread zu haben, ist wahrscheinlich viel komplizierter, dass zwei separate Threads verwendet wird, ist viel mehr fehleranfällig (Sie werden dafür sorgen müssen, dass die Verbraucher nie Blöcke für die Eingabe wartet, oder Sie‘ ll effektiv Deadlock) und würde erfordert die Erzeuger- und Verbraucher läuft in der gleichen Schleife, die Art und Weise zu scheint eng gekoppelt.

So ein zweites Gewinde verwenden. Es ist wirklich nicht so kompliziert. Die Seite, die Sie verknüpft hatte ein perfektes Beispiel:

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

Andere Tipps

Es gibt eine andere Open-Source-Bibliothek genannt EasyStream die sich mit Rohren und Gewinden in transparenter Weise. Das ist nicht wirklich kompliziert, wenn alles gut geht. Probleme entstehen, wenn (bei Laurence Gonsalves Beispiel suchen)

  

class1.putDataOnOutputStream (out);

Löst eine Ausnahme. In diesem Beispiel schließt der Faden einfach und die Ausnahme ist verloren, während die äußere InputStream möglicherweise abgeschnitten werden.

Easystream beschäftigt sich mit Ausnahme Ausbreitung und andere unangenehme Probleme, die ich schon seit etwa einem Jahr debuggen. (Ich bin der mantainer der Bibliothek: offensichtlich meine Lösung die beste ist;)) Hier ist ein Beispiel, wie man es verwenden:

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)
 }
};

Es gibt auch eine schöne Einführung wo alle anderen Möglichkeiten, um ein Outputstream zu konvertieren in einen Input erläutert. Lohnt sich, einen Blick zu haben.

Eine einfache Lösung, die den Puffer verhindert das Kopieren ist ein Spezial-ByteArrayOutputStream zu erstellen:

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);
    }
}

Schreiben des obigen Ausgangsstrom je nach Bedarf, dann toInputStream rufen einen Eingangsstrom über den darunterliegenden Puffer zu erhalten. Betrachten Sie den Ausgangsstrom als nach diesem Punkt geschlossen.

Ich denke, der beste Weg zu einem Inputoutput zu verbinden ist durch verrohrt Ströme - in java.io Paket, wie folgt:

// 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.*/

Meiner Meinung nach gibt es zwei wesentliche Vorteile für diesen Code:

1 - Es gibt keinen zusätzlichen Verbrauch von Speichern mit Ausnahme der Puffer

.

2 - Sie brauchen keine Daten zu verarbeiten Warteschlangen manuell

wegen der erhöhten Wahrscheinlichkeit von Deadlock

Ich versuche, in der Regel zu vermeiden, einen separaten Thread erstellen, die erhöhte Schwierigkeit, den Code zu verstehen, und die Probleme, mit Ausnahmen des Umgangs.

Hier ist meine vorgeschlagene Lösung: ein ProducerInputStream, die Inhalte in Stücke durch wiederholte Anrufe produceChunk erzeugt ():

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);

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top