Je suis au stade de développement, où j'ai deux modules et à partir de l'un, j'ai obtenu une sortie en tant que OutputStream
deuxième et un seul, qui accepte uniquement InputStream
. Savez - vous comment convertir OutputStream
à InputStream
( et non vice versa, je veux dire vraiment de cette façon) que je serai en mesure de relier ces deux parties?
Merci
java
inputstream
outputstream
Waypoint
la source
la source
new YourOutputStream(thePipedOutputStream)
etnew YourInputStream(thePipedInputStream)
ce n'est probablement pas la façon dont votre flux fonctionne. Je ne pense donc pas que ce soit la solution.Réponses:
Un
OutputStream
est celui où vous écrivez des données. Si un module expose unOutputStream
, on s'attend à ce qu'il y ait quelque chose à lire à l'autre bout.Quelque chose qui expose un
InputStream
, d'autre part, indique que vous devrez écouter ce flux et qu'il y aura des données que vous pourrez lire.Il est donc possible de connecter un
InputStream
à unOutputStream
InputStream----read---> intermediateBytes[n] ----write----> OutputStream
Comme quelqu'un l'a mentionné, c'est ce que la
copy()
méthode de IOUtils vous permet de faire. Cela n'a pas de sens d'aller dans l'autre sens ... j'espère que cela a du sensMETTRE À JOUR:
Bien sûr, plus j'y pense, plus je peux voir comment ce serait une exigence. Je connais certains des commentaires mentionnés
Piped
flux d'entrée / sortie, mais il existe une autre possibilité.Si le flux de sortie exposé est un
ByteArrayOutputStream
, vous pouvez toujours obtenir le contenu complet en appelant latoByteArray()
méthode. Ensuite, vous pouvez créer un wrapper de flux d'entrée à l'aide de laByteArrayInputStream
sous-classe. Ces deux sont des pseudo-flux, ils enveloppent simplement un tableau d'octets. L'utilisation des flux de cette façon est donc techniquement possible, mais pour moi, c'est encore très étrange ...la source
Il semble y avoir de nombreux liens et d'autres choses de ce genre, mais aucun code réel utilisant des canaux. L'avantage d'utiliser
java.io.PipedInputStream
etjava.io.PipedOutputStream
est qu'il n'y a pas de consommation supplémentaire de mémoire.ByteArrayOutputStream.toByteArray()
renvoie une copie du tampon d'origine, ce qui signifie que tout ce que vous avez en mémoire, vous en avez maintenant deux copies. Ensuite, en écrivant à unInputStream
moyen, vous disposez maintenant de trois copies des données.Le code:
Ce code suppose que le
originalByteArrayOutputStream
est unByteArrayOutputStream
car il est généralement le seul flux de sortie utilisable, sauf si vous écrivez dans un fichier. J'espère que ça aide! La grande chose à ce sujet est que, puisqu'il est dans un thread séparé, il fonctionne également en parallèle, donc tout ce qui consomme votre flux d'entrée sera également diffusé à partir de votre ancien flux de sortie. C'est avantageux car le tampon peut rester plus petit et vous aurez moins de latence et moins d'utilisation de mémoire.la source
out
auin
constructeur de, sinon vous pourriez obtenir une exception de tuyau fermé enin
raison de la condition de concurrence (que j'ai connue). Utilisation de Java 8 Lambdas:PipedInputStream in = new PipedInputStream(out); ((Runnable)() -> {originalOutputStream.writeTo(out);}).run(); return in;
originalOutputStream
ce qui devrait être vrai, mais il ne suppose pas comment vous contrôlez vos flux. Cela appartient au développeur. Il n'y a rien dans ce code qui provoquerait une exception de tuyau fermé ou cassé.PipedInputStream
Javadocs: Un canal serait rompu si un thread qui fournissait des octets de données au flux de sortie canalisé connecté n'était plus en vie. Donc, ce que je soupçonne, c'est que si vous utilisez l'exemple ci-dessus, le thread se termine avant deJax-RS
consommer le flux d'entrée. En même temps, j'ai regardé les Javadocs MongoDB .GridFSDBFile
a un flux d'entrée, alors pourquoi ne pas simplement le transmettre à Jax-RS ?Comme les flux d'entrée et de sortie ne sont que des points de début et de fin, la solution consiste à stocker temporairement les données dans un tableau d'octets. Vous devez donc créer un intermédiaire
ByteArrayOutputStream
, à partir duquel vous créezbyte[]
qui est utilisé comme entrée pour newByteArrayInputStream
.J'espère que ça aide.
la source
Vous aurez besoin d'une classe intermédiaire qui tamponnera entre. À chaque
InputStream.read(byte[]...)
appel, la classe de mise en mémoire tampon remplira le tableau d'octets transmis avec le bloc suivant transmis depuisOutputStream.write(byte[]...)
. Étant donné que les tailles des morceaux peuvent ne pas être les mêmes, la classe d'adaptateur devra stocker une certaine quantité jusqu'à ce qu'elle ait suffisamment pour remplir le tampon de lecture et / ou être capable de stocker tout débordement de tampon.Cet article présente une belle ventilation de quelques approches différentes de ce problème:
http://blog.ostermiller.org/convert-java-outputstream-inputstream
la source
la source
toByteArray()
corps de la méthode est comme celui-return Arrays.copyOf(buf, count);
ci et retourne un nouveau tableau.La bibliothèque open source easystream prend directement en charge la conversion d'un OutputStream en un InputStream: http://io-tools.sourceforge.net/easystream/tutorial/tutorial.html
Ils répertorient également d'autres options: http://io-tools.sourceforge.net/easystream/OutputStream_to_InputStream.html
la source
J'ai rencontré le même problème avec la conversion de a
ByteArrayOutputStream
en aByteArrayInputStream
et je l'ai résolu en utilisant une classe dérivée à partir deByteArrayOutputStream
laquelle est capable de retourner unByteArrayInputStream
qui est initialisé avec le tampon interne deByteArrayOutputStream
. De cette façon, aucune mémoire supplémentaire n'est utilisée et la «conversion» est très rapide:J'ai mis les trucs sur github: https://github.com/nickrussler/ByteArrayInOutStream
la source
La bibliothèque io-extras peut être utile. Par exemple, si vous voulez gziper un
InputStream
usingGZIPOutputStream
et que cela se produise de manière synchrone (en utilisant la taille de tampon par défaut de 8192):Notez que la bibliothèque a une couverture de test unitaire à 100% (pour ce que ça vaut bien sûr!) Et est sur Maven Central. La dépendance Maven est:
Assurez-vous de vérifier une version ultérieure.
la source
De mon point de vue, java.io.PipedInputStream / java.io.PipedOutputStream est la meilleure option à considérer. Dans certaines situations, vous souhaiterez peut-être utiliser ByteArrayInputStream / ByteArrayOutputStream. Le problème est que vous devez dupliquer le tampon pour convertir un ByteArrayOutputStream en ByteArrayInputStream. De même, ByteArrayOutpuStream / ByteArrayInputStream sont limités à 2 Go. Voici une implémentation OutpuStream / InputStream que j'ai écrite pour contourner les limitations de ByteArrayOutputStream / ByteArrayInputStream (code Scala, mais facilement compréhensible pour les développeurs Java):
Facile à utiliser, pas de duplication de tampon, pas de limite de mémoire de 2 Go
la source
Si vous voulez créer un OutputStream à partir d'un InputStream, il y a un problème de base. Une méthode qui écrit dans un bloc OutputStream jusqu'à ce qu'elle soit terminée. Le résultat est donc disponible lorsque la méthode d'écriture est terminée. Cela a 2 conséquences:
La variante 1 peut être implémentée à l'aide de tableaux d'octets ou déposée. La variante 1 peut être implémentée à l'aide de pipies (directement ou avec une abstraction supplémentaire - par exemple RingBuffer ou la bibliothèque google de l'autre commentaire).
En effet, avec java standard, il n'y a pas d'autre moyen de résoudre le problème. Chaque solution est une implémentation de l'une d'entre elles.
Il existe un concept appelé "continuation" (voir wikipedia pour plus de détails). Dans ce cas, cela signifie essentiellement:
Alors que certaines langues ont ce concept intégré, pour java, vous avez besoin de "magie". Par exemple "commons-javaflow" d'apache implémente un tel pour java. L'inconvénient est que cela nécessite des modifications de bytecode spéciales au moment de la construction. Il serait donc logique de mettre toutes les choses dans une bibliothèque supplémentaire avec des scripts de construction personnalisés.
la source
Ancien message mais pourrait aider les autres, utilisez cette méthode:
la source
toString().getBytes()
un flux * ne retournera pas le contenu du flux.Bien que vous ne puissiez pas convertir un OutputStream en un InputStream, java fournit un moyen d'utiliser PipedOutputStream et PipedInputStream que vous pouvez avoir des données écrites dans un PipedOutputStream pour devenir disponibles via un PipedInputStream associé.
Il y a quelque temps, j'ai fait face à une situation similaire lorsque je traitais avec des bibliothèques tierces qui exigeaient qu'une instance InputStream leur soit transmise au lieu d'une instance OutputStream.
La façon dont j'ai résolu ce problème consiste à utiliser PipedInputStream et PipedOutputStream.
Au fait, ils sont difficiles à utiliser et vous devez utiliser le multithreading pour obtenir ce que vous voulez. J'ai récemment publié une implémentation sur github que vous pouvez utiliser.
Voici le lien . Vous pouvez parcourir le wiki pour comprendre comment l'utiliser.
la source