Update in Java9: https://docs.oracle.com/javase/9/docs/api/java/io/InputStream.html#transferTo-java.io.OutputStream-
Ich habe einige ähnliche, aber nicht ganz das gesehen, was ich brauche.
Ich habe einen Server, der im Grunde Eingaben von einem Client, Client A, nimmt und diese Byte für Byte an einen anderen Client, Client B, weiterleitet.
Ich möchte meinen Eingabestream von Client A mit meinem Ausgabestream von Client B verbinden. Ist das möglich? Wie geht das?
Außerdem senden sich diese Clients gegenseitig Nachrichten, die etwas zeitkritisch sind, sodass das Puffern nicht ausreicht. Ich möchte keinen Puffer von beispielsweise 500 und ein Client sendet 499 Bytes. Dann hält mein Server die Weiterleitung der 500 Bytes zurück, da er nicht das letzte Byte empfangen hat, das den Puffer füllt.
Im Moment analysiere ich jede Nachricht, um ihre Länge zu ermitteln, lese dann Längenbytes und leite sie weiter. Ich dachte (und testete), dass dies besser wäre, als ein Byte zu lesen und ein Byte immer wieder weiterzuleiten, da dies sehr langsam wäre. Ich wollte aus dem Grund, den ich in meinem letzten Absatz angegeben habe, auch keinen Puffer oder Timer verwenden - ich möchte nicht, dass Nachrichten, die wirklich lange warten, durchkommen, nur weil der Puffer nicht voll ist.
Was ist ein guter Weg, um dies zu tun?
close()
Wille es trotzdem spült , denke ich nicht, dass es sich persönlich lohnt. Wenn Sie Code wie diesen nehmen, können Sie ihn natürlich gerne hinzufügen :)Wie wäre es einfach mit
void feedInputToOutput(InputStream in, OutputStream out) { IOUtils.copy(in, out); }
und damit fertig sein?
aus der jakarta apache commons i / o Bibliothek, die bereits von einer Vielzahl von Projekten verwendet wird, sodass Sie das Glas wahrscheinlich bereits in Ihrem Klassenpfad haben.
quelle
Der Vollständigkeit halber hat Guave auch ein nützliches Dienstprogramm dafür
quelle
JDK 9 hat
InputStream#transferTo(OutputStream out)
für diese Funktionalität hinzugefügt .quelle
Sie können einen Ringpuffer verwenden:
Code
// buffer all data in a circular buffer of infinite size CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE); class1.putDataOnOutputStream(cbb.getOutputStream()); class2.processDataFromInputStream(cbb.getInputStream());
Maven-Abhängigkeit
<dependency> <groupId>org.ostermiller</groupId> <artifactId>utils</artifactId> <version>1.07.00</version> </dependency>
Modendetails
http://ostermiller.org/utils/CircularBuffer.html
quelle
Asynchroner Weg, um dies zu erreichen.
void inputStreamToOutputStream(final InputStream inputStream, final OutputStream out) { Thread t = new Thread(new Runnable() { public void run() { try { int d; while ((d = inputStream.read()) != -1) { out.write(d); } } catch (IOException ex) { //TODO make a callback on exception. } } }); t.setDaemon(true); t.start(); }
quelle
BUFFER_SIZE ist die Größe der einzulesenden Spannfutter. Sollte> 1 KB und <10 MB sein.
private static final int BUFFER_SIZE = 2 * 1024 * 1024; private void copy(InputStream input, OutputStream output) throws IOException { try { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = input.read(buffer); while (bytesRead != -1) { output.write(buffer, 0, bytesRead); bytesRead = input.read(buffer); } //If needed, close streams. } finally { input.close(); output.close(); } }
quelle
Verwenden Sie org.apache.commons.io.IOUtils
InputStream inStream = new ... OutputStream outStream = new ... IOUtils.copy(inStream, outStream);
oder copyLarge für Größe> 2 GB
quelle
Dies ist eine Scala-Version, die sauber und schnell ist (kein Stackoverflow):
import scala.annotation.tailrec import java.io._ implicit class InputStreamOps(in: InputStream) { def >(out: OutputStream): Unit = pipeTo(out) def pipeTo(out: OutputStream, bufferSize: Int = 1<<10): Unit = pipeTo(out, Array.ofDim[Byte](bufferSize)) @tailrec final def pipeTo(out: OutputStream, buffer: Array[Byte]): Unit = in.read(buffer) match { case n if n > 0 => out.write(buffer, 0, n) pipeTo(out, buffer) case _ => in.close() out.close() } }
Dies ermöglicht die Verwendung von
>
Symbolen zBinputstream > outputstream
und die Übergabe von benutzerdefinierten Puffern / Größen.quelle
Wenn Sie sich für Funktionen interessieren, ist dies eine in Scala geschriebene Funktion, die zeigt, wie Sie einen Eingabestream nur mit vals (und nicht mit vars) in einen Ausgabestream kopieren können.
def copyInputToOutputFunctional(inputStream: InputStream, outputStream: OutputStream,bufferSize: Int) { val buffer = new Array[Byte](bufferSize); def recurse() { val len = inputStream.read(buffer); if (len > 0) { outputStream.write(buffer.take(len)); recurse(); } } recurse(); }
Beachten Sie, dass dies nicht für die Verwendung in einer Java-Anwendung mit wenig verfügbarem Speicher empfohlen wird, da bei einer rekursiven Funktion leicht ein Stapelüberlauf-Ausnahmefehler auftreten kann
quelle