Estoy en la etapa de desarrollo, donde tengo dos módulos y de uno obtuve salida como uno OutputStream
y segundo, que solo acepta InputStream
. ¿Sabe usted cómo convertir OutputStream
a InputStream
(y no al revés, me refiero a realmente de esta manera) que voy a ser capaz de conectar estas dos partes?
Gracias
java
inputstream
outputstream
Punto de referencia
fuente
fuente
new YourOutputStream(thePipedOutputStream)
ynew YourInputStream(thePipedInputStream)
probablemente no sea así como funciona su transmisión. Entonces no creo que esta sea la solución.Respuestas:
An
OutputStream
es aquel en el que escribe datos. Si algún módulo expone unOutputStream
, la expectativa es que hay algo leyendo en el otro extremo.Algo que expone y
InputStream
, por otro lado, indica que necesitará escuchar esta transmisión, y habrá datos que podrá leer.Por lo tanto, es posible conectar un
InputStream
a unOutputStream
InputStream----read---> intermediateBytes[n] ----write----> OutputStream
Como alguien mencionó, esto es lo que el
copy()
método de IOUtils le permite hacer. No tiene sentido ir hacia otro lado ... espero que esto tenga algún sentidoACTUALIZAR:
Por supuesto, cuanto más pienso en esto, más puedo ver cómo esto sería realmente un requisito. Sé que algunos de los comentarios mencionaron
Piped
flujos de entrada / salida, pero hay otra posibilidad.Si la secuencia de salida que está expuesta es a
ByteArrayOutputStream
, entonces siempre puede obtener el contenido completo llamando altoByteArray()
método. Luego puede crear un contenedor de flujo de entrada utilizando laByteArrayInputStream
subclase. Estos dos son pseudo-flujos, ambos básicamente solo envuelven una matriz de bytes. Usar las transmisiones de esta manera, por lo tanto, es técnicamente posible, pero para mí sigue siendo muy extraño ...fuente
Parece que hay muchos enlaces y otras cosas similares, pero no hay código real que use tuberías. La ventaja de usar
java.io.PipedInputStream
yjava.io.PipedOutputStream
es que no hay consumo adicional de memoria.ByteArrayOutputStream.toByteArray()
devuelve una copia del búfer original, lo que significa que, sea lo que sea que tenga en la memoria, ahora tiene dos copias. Luego, escribir en unInputStream
medio significa que ahora tiene tres copias de los datos.El código:
Este código supone que
originalByteArrayOutputStream
es un,ByteArrayOutputStream
ya que generalmente es la única secuencia de salida utilizable, a menos que esté escribiendo en un archivo. ¡Espero que esto ayude! Lo bueno de esto es que, dado que está en un hilo separado, también funciona en paralelo, por lo que lo que sea que esté consumiendo su flujo de entrada también se transmitirá desde su flujo de salida anterior. Eso es beneficioso porque el búfer puede permanecer más pequeño y tendrá menos latencia y menos uso de memoria.fuente
out
alin
constructor, de lo contrario, podría obtener una excepción de tubería cerradain
debido a la condición de la carrera (que experimenté). Usando Java 8 Lambdas:PipedInputStream in = new PipedInputStream(out); ((Runnable)() -> {originalOutputStream.writeTo(out);}).run(); return in;
originalOutputStream
que debería ser cierto, pero no asume cómo controla sus transmisiones. Eso queda en manos del desarrollador. No hay nada en este código que pueda causar una excepción de tubería cerrada o rota.PipedInputStream
Javadocs: se dice que una tubería se rompe si un hilo que proporcionaba bytes de datos a la secuencia de salida de tubería conectada ya no está vivo. Entonces, lo que sospecho es que si está utilizando el ejemplo anterior, el hilo se está completando antes deJax-RS
consumir la secuencia de entrada. Al mismo tiempo, miré los Javadocs de MongoDB .GridFSDBFile
tiene un flujo de entrada, entonces ¿por qué no simplemente pasar eso a Jax-RS ?Como los flujos de entrada y salida son solo el punto inicial y final, la solución es almacenar temporalmente los datos en una matriz de bytes. Por lo tanto, debe crear intermedios
ByteArrayOutputStream
, a partir de los cuales creabyte[]
que se utilizan como entrada para nuevosByteArrayInputStream
.Espero eso ayude.
fuente
Necesitará una clase intermedia que amortiguará entre. Cada vez que
InputStream.read(byte[]...)
se llama, la clase de almacenamiento en búfer llenará la matriz de bytes pasada con el siguiente fragmento pasadoOutputStream.write(byte[]...)
. Dado que los tamaños de los fragmentos pueden no ser los mismos, la clase de adaptador deberá almacenar una cierta cantidad hasta que tenga suficiente para llenar el búfer de lectura y / o poder almacenar cualquier desbordamiento del búfer.Este artículo tiene un buen desglose de algunos enfoques diferentes para este problema:
http://blog.ostermiller.org/convert-java-outputstream-inputstream
fuente
fuente
toByteArray()
que el cuerpo del método es así, loreturn Arrays.copyOf(buf, count);
que devuelve una nueva matriz.La biblioteca de código abierto easystream tiene soporte directo para convertir un OutputStream en un InputStream: http://io-tools.sourceforge.net/easystream/tutorial/tutorial.html
También enumeran otras opciones: http://io-tools.sourceforge.net/easystream/OutputStream_to_InputStream.html
fuente
Encontré el mismo problema con la conversión de a
ByteArrayOutputStream
aByteArrayInputStream
y lo resolví usando una clase derivada de laByteArrayOutputStream
cual es capaz de devolver unByteArrayInputStream
que se inicializa con el búfer interno delByteArrayOutputStream
. De esta forma no se usa memoria adicional y la 'conversión' es muy rápida:Puse las cosas en github: https://github.com/nickrussler/ByteArrayInOutStream
fuente
La biblioteca io-extras puede ser útil. Por ejemplo, si desea comprimir un
InputStream
usoGZIPOutputStream
y quiere que suceda sincrónicamente (usando el tamaño de búfer predeterminado de 8192):Tenga en cuenta que la biblioteca tiene una cobertura de prueba de unidad del 100% (¡por lo que vale, por supuesto!) Y está en Maven Central. La dependencia de Maven es:
Asegúrese de buscar una versión posterior.
fuente
Desde mi punto de vista, java.io.PipedInputStream / java.io.PipedOutputStream es la mejor opción para considerar. En algunas situaciones, es posible que desee utilizar ByteArrayInputStream / ByteArrayOutputStream. El problema es que necesita duplicar el búfer para convertir un ByteArrayOutputStream en un ByteArrayInputStream. También ByteArrayOutpuStream / ByteArrayInputStream están limitados a 2GB. Aquí hay una implementación OutpuStream / InputStream que escribí para evitar las limitaciones de ByteArrayOutputStream / ByteArrayInputStream (código Scala, pero fácilmente comprensible para los desarrolladores de Java):
Fácil de usar, sin duplicación de búfer, sin límite de memoria de 2 GB
fuente
Si desea hacer un OutputStream desde un InputStream, hay un problema básico. Un método que escribe en un bloque OutputStream hasta que se hace. Por lo tanto, el resultado está disponible cuando finaliza el método de escritura. Esto tiene 2 consecuencias:
La variante 1 se puede implementar utilizando matrices de bytes o archivada. La variante 1 se puede implementar usando pipies (ya sea directamente o con abstracción adicional, por ejemplo, RingBuffer o google lib del otro comentario).
De hecho, con Java estándar no hay otra forma de resolver el problema. Cada solución es una implementación de uno de estos.
Hay un concepto llamado "continuación" (ver wikipedia para más detalles). En este caso, básicamente esto significa:
Si bien algunos idiomas tienen este concepto incorporado, para Java necesitas algo de "magia". Por ejemplo, "commons-javaflow" de apache implementa tales como java. La desventaja es que esto requiere algunas modificaciones especiales de código de bytes en el momento de la compilación. Por lo tanto, tendría sentido poner todo el material en una biblioteca adicional con scripts de compilación personalizados.
fuente
Publicación anterior, pero podría ayudar a otros. Use esta forma:
fuente
toString().getBytes()
a una secuencia * no devolverá el contenido de la secuencia.Aunque no puede convertir un OutputStream en un InputStream, java proporciona una forma de usar PipedOutputStream y PipedInputStream para que pueda tener datos escritos en un PipedOutputStream para que estén disponibles a través de un PipedInputStream asociado.
En algún momento, enfrenté una situación similar al tratar con bibliotecas de terceros que requerían que se les pasara una instancia de InputStream en lugar de una instancia de OutputStream.
La forma en que solucioné este problema es usar PipedInputStream y PipedOutputStream.
Por cierto, son difíciles de usar y debes usar subprocesos múltiples para lograr lo que deseas. Recientemente publiqué una implementación en github que puedes usar.
Aquí está el enlace . Puedes revisar la wiki para entender cómo usarla.
fuente