93 votes

Le moyen le plus efficace pour créer InputStream de OutputStream

Cette page: http://ostermiller.org/convert_java_outputstream_inputstream.html

décrit comment créer un InputStream de OutputStream:

new ByteArrayInputStream(out.toByteArray())

D'autres solutions sont à utiliser PipedStreams et de nouveaux threads, ce qui est contraignant.

Je n'aime pas l'idée de la copie de plusieurs méga-octets à nouveau dans la mémoire du tableau d'Octets. Est-il une bibliothèque qui permet de le faire de manière plus efficace ?

EDIT:

Par conseiller de Laurence Gonsalves, j'ai essayé PipedStreams et il s'est avéré qu'ils ne sont pas si difficile à traiter. Voici l'exemple de code dans 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))

77voto

Laurence Gonsalves Points 50783

Si vous ne souhaitez pas copier toutes les données dans un tampon en mémoire, tout à la fois, alors vous allez avoir votre code qui utilise la OutputStream (le producteur) et le code qui utilise l'InputStream (le consommateur), soit une alternance dans le même thread, ou de faire fonctionner simultanément dans deux threads différents. Avoir entre eux opèrent dans le même thread est probablement beaucoup plus complexe que l'utilisation de deux threads différents, est beaucoup plus sujettes à erreur (vous aurez besoin pour vous assurer que le consommateur ne jamais blocs d'attente pour l'entrée, ou vous aurez effectivement de blocage) et nécessiterait d'avoir le producteur et le consommateur cours d'exécution dans la même boucle qui semble trop étroitement couplées.

Il faut donc utiliser un deuxième thread. Ce n'est vraiment pas compliqué. La page que vous avez lié à eu un parfait exemple:

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

15voto

Gab Points 437

Il y a une autre bibliothèque Open Source appelé EasyStream qui traite avec des pipes et du fil de façon transparente. Ce n'est pas vraiment compliqué si tout va bien. Les problèmes surviennent lorsque (regardant Laurence Gonsalves exemple)

class1.putDataOnOutputStream(out);

Lève une exception. Dans cet exemple, le fil tout simplement se termine et l'exception est perdu, tandis que l'extérieur InputStream risquent d'être tronqués.

Easystream traite de la propagation d'exception et d'autres méchants problèmes que j'ai été le débogage pendant environ un an. (Je suis le mantainer de la bibliothèque: évidemment, ma solution est la meilleure ;) ) Voici un exemple sur la façon de l'utiliser:

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

Il ya aussi une belle introduction où tous les autres moyens de convertir un OutputStream dans un InputStream sont expliqués. Est utile d'avoir un coup d'oeil.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X