2015-01-18 15 views
11

Ho letto molto su Iteratees & Enumeratori per implementare un nuovo modulo nella mia applicazione.Creazione di un InputStream Java da un enumeratore [Array [Byte]]

sono ora ad un punto in cui sto integrando con una libreria Java 3rd party, e sono bloccato a lavorare con questo metodo:

public Email addAttachment(String name, InputStream file) throws IOException { 
    this.attachments.put(name, file); 
    return this; 
} 

Quello che ho nel mio API è il corpo tornato da a WS Chiamata HTTP che è Enumerator[Array[Byte]].

Mi chiedo ora come scrivere un Iteratee che elabora i blocchi di Array[Bytes] e crei un InputStream da utilizzare con questo metodo.

(barra laterale): esistono altre versioni del metodo addAttachment che richiedono java.io.File tuttavia, in questa operazione, desidero evitare di scrivere sul disco e preferirei gestire gli stream.

ho cercato di iniziare scrivendo qualcosa di simile:

Iteratee.foreach[Array[Byte]] { bytes => 
    ??? 
} 

Tuttavia io non sono sicuro di come interagire con il java InputStream qui. Ho trovato qualcosa chiamato ByteArrayInputStream, ma che prende l'intero Array[Byte] nel suo costruttore, che non sono sicuro che funzionerebbe in questo scenario, visto che sto lavorando con chunk?

Probabilmente ho bisogno di un aiuto Java qui!

Grazie per qualsiasi aiuto in anticipo.

+0

Questo è difficile. Penso che la cosa migliore da fare sia creare un'implementazione dell'interfaccia InputStream con l'enumeratore sottostante. E poi su ogni chiamata 'read', consumare la quantità necessaria di byte dall'Enumeratore. – Martijn

+0

Oltre a ciò, penso che la soluzione migliore è la memorizzazione nella cache di tutto e l'immissione in ByteArrayInputStream. Il problema è che Enumerator è un flusso di dati con una meccanica push e InputStream utilizza una meccanica di pull, il che significa che è necessario avere un buffer da qualche parte altrimenti non funzionerà. Puoi bufferizzare tutto per ora, e magari decidere in seguito, cosa fare quando le prestazioni stanno diventando un collo di bottiglia. Forse fai dei buffer parziali, ottieni il punto. – Martijn

+2

Non ho ancora testato questo, ma ho provato qualcosa di simile: 'consumano val = corpo | >>> Iteratee.consume [Array [Byte]]()' Poi 'nuova ByteArrayInputStream (consumare)' tardi . Penso che questa sia una ingenua implementazione del tuo secondo commento, tuttavia senza il buffering. –

risposta

3

Se ti sto seguendo, penso che si desidera lavorare con PipedInputStream e PipedOutputStream:

https://docs.oracle.com/javase/8/docs/api/java/io/PipedInputStream.html

di utilizzarli sempre in coppia. È possibile costruire la coppia in questo modo:

PipedInputStream in = new PipedInputStream(); //can also specify a buffer size 
PipedOutputStream out = new PipedOutputSream(in); 

Passare il flusso di input per l'API, e nel proprio codice iterare attraverso i mandrini e scrivere il byte.

L'unica avvertenza è che è necessario leggere/scrivere in thread separati. Nel tuo caso, è probabilmente utile fare la tua iterazione/scrittura in un thread separato. Sono sicuro che si può gestire a Scala meglio di me, in Java sarebbe qualcosa di simile:

PipedInputStream in = new PipedInputStream(); //can also specify a buffer size 
PipedOutputStream out = new PipedOutputSream(out); 
new Thread(() -> { 
    // do your looping in here, write to 'out' 
    out.close(); 
}).run(); 
email.addAttachment(in); 
email.send(); 
in.close(); 

(Tralasciando gestione delle eccezioni & gestione delle risorse per chiarezza)

Problemi correlati