Estou no estágio de desenvolvimento, onde tenho dois módulos e, de um, obtive saída como um OutputStream
e segundo, que aceita apenas InputStream
. Sabe como converter OutputStream
para InputStream
(e não vice-versa, eu quero dizer realmente desta forma) que vou ser capaz de se conectar essas duas partes?
obrigado
java
inputstream
outputstream
Parada
fonte
fonte
new YourOutputStream(thePipedOutputStream)
enew YourInputStream(thePipedInputStream)
provavelmente não é assim que o seu fluxo funciona. Então, eu não acho que essa seja a solução.Respostas:
Um
OutputStream
é aquele em que você grava dados. Se algum módulo expuser umOutputStream
, a expectativa é que haja algo lendo no outro extremo.Algo que expõe um
InputStream
, por outro lado, indica que você precisará ouvir esse fluxo e haverá dados que você poderá ler.Portanto, é possível conectar um
InputStream
a umOutputStream
InputStream----read---> intermediateBytes[n] ----write----> OutputStream
Como alguém mencionou, é isso que o
copy()
método do IOUtils permite que você faça. Não faz sentido seguir para o outro lado ... espero que isso faça algum sentidoATUALIZAR:
É claro que quanto mais penso nisso, mais posso ver como isso realmente seria um requisito. Conheço alguns dos comentários mencionados
Piped
fluxos de entrada / saída, mas há outra possibilidade.Se o fluxo de saída exposto for a
ByteArrayOutputStream
, você poderá obter todo o conteúdo chamando otoByteArray()
método Em seguida, você pode criar um wrapper de fluxo de entrada usando aByteArrayInputStream
subclasse. Esses dois são pseudo-fluxos, ambos basicamente apenas envolvem uma matriz de bytes. Usar os fluxos dessa maneira, portanto, é tecnicamente possível, mas para mim ainda é muito estranho ...fonte
Parece haver muitos links e outras coisas desse tipo, mas nenhum código real usando pipes. A vantagem de usar
java.io.PipedInputStream
ejava.io.PipedOutputStream
é que não há consumo adicional de memória.ByteArrayOutputStream.toByteArray()
retorna uma cópia do buffer original, o que significa que, o que quer que você tenha na memória, agora você tem duas cópias. Em seguida, escrevendo para umInputStream
meio, você agora tem três cópias dos dados.O código:
Esse código pressupõe que o
originalByteArrayOutputStream
é umByteArrayOutputStream
, pois geralmente é o único fluxo de saída utilizável, a menos que você esteja gravando em um arquivo. Eu espero que isso ajude! O melhor disso é que, como está em um encadeamento separado, ele também está trabalhando em paralelo; portanto, o que estiver consumindo seu fluxo de entrada também sairá do seu antigo fluxo de saída. Isso é benéfico porque o buffer pode permanecer menor e você terá menos latência e menos uso de memória.fonte
out
parain
o construtor, caso contrário, você poderá receber uma exceção de tubo fechadoin
devido à condição de corrida (que eu experimentei). Usando Java 8 Lambdas:PipedInputStream in = new PipedInputStream(out); ((Runnable)() -> {originalOutputStream.writeTo(out);}).run(); return in;
originalOutputStream
que deve ser verdadeiro, mas não assume como você controla seus fluxos. Isso é deixado para o desenvolvedor. Não há nada neste código que possa causar uma exceção de canal fechado ou quebrado.PipedInputStream
Javadocs: Diz-se que um pipe está quebrado se um encadeamento que estava fornecendo bytes de dados para o fluxo de saída canalizado conectado não estiver mais ativo. Então, o que eu suspeito é que, se você estiver usando o exemplo acima, o encadeamento está sendo concluído antesJax-RS
e consumindo o fluxo de entrada. Ao mesmo tempo, observei os Javadocs do MongoDB .GridFSDBFile
tem um fluxo de entrada, então por que não passar isso para o Jax-RS ?Como os fluxos de entrada e saída são apenas o ponto inicial e final, a solução é armazenar dados temporariamente na matriz de bytes. Portanto, você deve criar intermediários
ByteArrayOutputStream
, a partir dos quais você cria,byte[]
que é usado como entrada para novosByteArrayInputStream
.Espero que ajude.
fonte
Você precisará de uma classe intermediária que fará o buffer entre. Cada vez que
InputStream.read(byte[]...)
é chamada, a classe de buffer preenche a matriz de bytes passada com o próximo pedaço passado deOutputStream.write(byte[]...)
. Como os tamanhos dos chunks podem não ser os mesmos, a classe do adaptador precisará armazenar uma certa quantia até ter o suficiente para preencher o buffer de leitura e / ou poder armazenar qualquer estouro de buffer.Este artigo possui uma boa descrição de algumas abordagens diferentes para esse problema:
http://blog.ostermiller.org/convert-java-outputstream-inputstream
fonte
fonte
toByteArray()
corpo do método é assim,return Arrays.copyOf(buf, count);
e retorna uma nova matriz.A biblioteca de software livre easystream possui suporte direto para converter um OutputStream em um InputStream: http://io-tools.sourceforge.net/easystream/tutorial/tutorial.html
Eles também listam outras opções: http://io-tools.sourceforge.net/easystream/OutputStream_to_InputStream.html
fonte
Encontrei o mesmo problema ao converter a
ByteArrayOutputStream
em aByteArrayInputStream
e resolvi-o usando uma classe derivada daByteArrayOutputStream
qual é possível retornar umByteArrayInputStream
que é inicializado com o buffer interno doByteArrayOutputStream
. Dessa forma, nenhuma memória adicional é usada e a 'conversão' é muito rápida:Coloquei as coisas no github: https://github.com/nickrussler/ByteArrayInOutStream
fonte
A biblioteca io-extras pode ser útil. Por exemplo, se você deseja compactar um zip com um
InputStream
usoGZIPOutputStream
e deseja que isso ocorra de forma síncrona (usando o tamanho padrão do buffer 8192):Observe que a biblioteca possui 100% de cobertura de teste de unidade (pelo que vale a pena, é claro!) E está no Maven Central. A dependência do Maven é:
Certifique-se de verificar se há uma versão posterior.
fonte
Do meu ponto de vista, java.io.PipedInputStream / java.io.PipedOutputStream é a melhor opção para considerar. Em algumas situações, convém usar ByteArrayInputStream / ByteArrayOutputStream. O problema é que você precisa duplicar o buffer para converter um ByteArrayOutputStream em um ByteArrayInputStream. ByteArrayOutpuStream / ByteArrayInputStream também são limitados a 2 GB. Aqui está uma implementação OutpuStream / InputStream que escrevi para ignorar as limitações de ByteArrayOutputStream / ByteArrayInputStream (código Scala, mas facilmente compreensível para desenvolvedores java):
Fácil de usar, sem duplicação de buffer, sem limite de memória de 2 GB
fonte
Se você deseja criar um OutputStream a partir de um InputStream, há um problema básico. Um método que grava em um OutputStream bloqueia até que seja concluído. Portanto, o resultado está disponível quando o método de gravação é concluído. Isso tem duas consequências:
A variante 1 pode ser implementada usando matrizes de bytes ou arquivadas. A variante 1 pode ser implementada usando pipies (diretamente ou com abstração extra - por exemplo, RingBuffer ou google lib do outro comentário).
De fato, com o java padrão, não há outra maneira de resolver o problema. Cada solução é uma implementação de um deles.
Há um conceito chamado "continuação" (consulte a Wikipedia para detalhes). Neste caso, basicamente, isso significa:
Enquanto algumas linguagens têm esse conceito embutido, para o java você precisa de alguma "mágica". Por exemplo, "commons-javaflow" do apache implementa como o java. A desvantagem é que isso requer algumas modificações especiais de código de byte no tempo de construção. Portanto, faria sentido colocar todas as coisas em uma biblioteca extra com scripts de construção personalizados.
fonte
Postagem antiga, mas pode ajudar outras pessoas, use desta maneira:
fonte
toString().getBytes()
um fluxo * não retornará o conteúdo do fluxo.Embora você não possa converter um OutputStream em um InputStream, o java fornece uma maneira, usando PipedOutputStream e PipedInputStream, de que você pode ter dados gravados em um PipedOutputStream para se tornarem disponíveis através de um PipedInputStream associado.
Algum tempo atrás, enfrentei uma situação semelhante ao lidar com bibliotecas de terceiros que exigiam que uma instância InputStream fosse passada a elas, em vez de uma instância OutputStream.
A maneira que eu corrigi esse problema é usar o PipedInputStream e o PipedOutputStream.
A propósito, eles são difíceis de usar e você deve usar o multithreading para conseguir o que deseja. Publiquei recentemente uma implementação no github que você pode usar.
Aqui está o link . Você pode acessar o wiki para entender como usá-lo.
fonte