Connection of the input stream to the output stream

update in java9: https://docs.oracle.com/javase/9/docs/api/java/io/InputStream.html#transferTo-java.io.OutputStream-

I saw some similar, but not absolutely necessary flows.

I have a server that will basically receive data from client, client A and forward it, byte for byte, to another client, client B.

I want to connect my client A input stream to my client B output stream. Is this possible? What are the ways to do this?

In addition, these clients send each other messages that are somewhat time sensitive, so buffering will not be performed. I do not want the buffer to say 500, and the client sends 499 bytes, and then my server holds 500 bytes when forwarding because it did not receive the last byte to fill the buffer.

Currently, I am parsing each message to find its length, then reading the length bytes and then forwarding them. I decided (and experienced) that it would be better than reading a byte and forwarding the byte again and again, because it would be very slow. I also did not want to use a buffer or timer for the reason that I mentioned in my last paragraph - I do not want messages to wait a very long time to go through simply because the buffer is not full.

What a good way to do this?

+66
java inputstream outputstream
Oct 15 '09 at 20:29
source share
10 answers

Just because you use a buffer does not mean that the stream must fill this buffer. In other words, this should be good:

public static void copyStream(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[1024]; // Adjust if you want int bytesRead; while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); } } 

This should work fine - basically, the read call will block until some data is available, but it will not wait until it becomes available to fill the buffer. (I believe this is possible, and I believe that FileInputStream usually fills the buffer, but a stream connected to the socket will most likely give you data immediately.)

I think it’s worth at least trying this simple solution.

+79
Oct. 15 '09 at 20:33
source share

How easy to use

 void feedInputToOutput(InputStream in, OutputStream out) { IOUtils.copy(in, out); } 

and do with it?

from the jacarta apache commons i / o library, which is already in use by a huge number of projects, so you probably already have a jar in your class path.

+65
Feb 28 2018-12-12T00:
source share

For completeness, guava also has a handy utility for this.

 ByteStreams.copy(input, output); 
+20
Sep 08 '13 at 6:18
source share

You can use a circular buffer:

the 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 addiction

 <dependency> <groupId>org.ostermiller</groupId> <artifactId>utils</artifactId> <version>1.07.00</version> </dependency> 


Mode Details

http://ostermiller.org/utils/CircularBuffer.html

+9
Nov 25 2018-11-11T00:
source share

Asynchronous way to achieve it.

 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(); } 
+5
Jun 28 2018-12-12T00: 00Z
source share
+4
Mar 10 '17 at 3:27
source share

BUFFER_SIZE - size of cartridges for reading. Must be> 1kb and <10MB.

 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(); } } 
+2
Apr 28 '15 at 9:44
source share

This is a version of Scala that is clean and fast (without 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() } } 

This allows you to use the > character, for example. inputstream > outputstream , as well as pass custom buffers / sizes.

+1
Sep 17 '15 at 18:26
source share

Use org.apache.commons.io.IOUtils

 InputStream inStream = new ... OutputStream outStream = new ... IOUtils.copy(inStream, outStream); 

or copyLarge for size> 2 GB

0
Oct 20 '17 at 7:01
source share

If you are entering functionality, this is a function written in Scala showing how you can copy the input stream to the output stream using only vals (not vars).

 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(); } 

Please note that this is not recommended for use in a Java application with a small amount of available memory, since using a recursive function you can easily get an exception error

-fourteen
Mar 20 '13 at 12:46
source share



All Articles