How to make a copy of InputStream Object

M

manjunath.d

Hi Friends,

I require your help in implementing a copy of InputStream objects.

My scenario is that I need to pass InputStream objects to a 3rd party
application, which closes the stream. *But*, I require the same
InputStream object for querying for other attributes. Basically, What I
mean is that, I need to make copy of InputStream object and then use
each object for the 3rd party application

InputStream inputStream = getFileStream();

for(int i = 0; i < attrs.length; i++)
{
ThirdParty.process( inputStream, attrs);
//But basically, the inputStream gets closed after first
iteration.
}


Please note: I cannot invoke getFileStream each time. My App receives
the inputStream obj from another application


Thanks
 
A

Arnaud Berger

Hi,

I'm pretty sure that an InputStream cannot be cloned.

However, if the third-party app doesn't close the stream, you may "mark" the
stream
before giving it to the 3rd party, then "reset" it afterwards.

Regards,

Arnaud

Hi Friends,

I require your help in implementing a copy of InputStream objects.

My scenario is that I need to pass InputStream objects to a 3rd party
application, which closes the stream. *But*, I require the same
InputStream object for querying for other attributes. Basically, What I
mean is that, I need to make copy of InputStream object and then use
each object for the 3rd party application

InputStream inputStream = getFileStream();

for(int i = 0; i < attrs.length; i++)
{
ThirdParty.process( inputStream, attrs);
file://But basically, the inputStream gets closed after first
iteration.
}


Please note: I cannot invoke getFileStream each time. My App receives
the inputStream obj from another application


Thanks
Manjunath
 
R

Ross Bamford

Hi Friends,

I require your help in implementing a copy of InputStream objects.

My scenario is that I need to pass InputStream objects to a 3rd party
application, which closes the stream. *But*, I require the same
InputStream object for querying for other attributes. Basically, What I
mean is that, I need to make copy of InputStream object and then use
each object for the 3rd party application

InputStream inputStream = getFileStream();

for(int i = 0; i < attrs.length; i++)
{
ThirdParty.process( inputStream, attrs);
//But basically, the inputStream gets closed after first
iteration.
}


Please note: I cannot invoke getFileStream each time. My App receives
the inputStream obj from another application


Thanks
Manjunath


Give the third party a wrapper that writes it's data through to your
stream. You create it for the call backed by your stream, pass it out,
third party closes it, you move on with your original stream (perhaps
doing same thing again).

Cheers,
Ross
 
J

John C. Bollinger

Ross said:
Hi Friends,

I require your help in implementing a copy of InputStream objects.

My scenario is that I need to pass InputStream objects to a 3rd party
application, which closes the stream. *But*, I require the same
InputStream object for querying for other attributes. Basically, What I
mean is that, I need to make copy of InputStream object and then use
each object for the 3rd party application

InputStream inputStream = getFileStream();

for(int i = 0; i < attrs.length; i++)
{
ThirdParty.process( inputStream, attrs);
//But basically, the inputStream gets closed after first
iteration.
}


Please note: I cannot invoke getFileStream each time. My App receives
the inputStream obj from another application


Thanks
Manjunath


Give the third party a wrapper that writes it's data through to your
stream. You create it for the call backed by your stream, pass it out,
third party closes it, you move on with your original stream (perhaps
doing same thing again).


Right. Do note, however, that you cannot reread the data that the
3rd-party reads from the stream -- whatever was read from the stream is
gone. That may or may not be what you want. If it _isn't_ what you
want then you can still achieve your objective, but it will require a
more complex wrapper that buffers a copy of the data read from it (into
a ByteArrayOutputStream, for instance). Beware that such an approach is
inherently limited by available memory, whereas the unbuffered version
isn't.
 
M

manjunath.d

Guys,
Thanks for your replies.

I have implemented the solution (as follows) but there is heavy
performance hit. Can you think of a better solution?

1. Read the original stream into a ByteArrayOutputStream obj
2. Each there is a request for the stream, I create a
ByteArrayInputStream obj from the above ByteArrayOutputStream obj.
(StreamFactory)
3. Third party app may close the stream, but that doesnt have effect on
my StreamFactory.

Do you suggest a better approach?

Thanks
 
R

Rogan Dawes

Guys,
Thanks for your replies.

I have implemented the solution (as follows) but there is heavy
performance hit. Can you think of a better solution?

1. Read the original stream into a ByteArrayOutputStream obj
2. Each there is a request for the stream, I create a
ByteArrayInputStream obj from the above ByteArrayOutputStream obj.
(StreamFactory)
3. Third party app may close the stream, but that doesnt have effect on
my StreamFactory.

Do you suggest a better approach?

Thanks

Create a CopyInputStream:

VERY roughly, add your own boilerplate, etc

public class CopyInputStream extends FilterInputStream {

private ByteArrayOutputStream _copy = new ByteArrayOutputStream();

public CopyInputStream(InputStream is) {
_is = is;
}

public int read() throws IOException {
int got = is.read();
if (got>-1) {
_copy.write((byte)got);
}
return got;
}

public InputStream getCopy() {
return new ByteArrayInputStream(copy.getBytes());
}

}

Implement int read(byte[] buff, int off, int len) as well for better
performance if required . . .

Regards,

Rogan
 
Joined
Jul 6, 2010
Messages
1
Reaction score
0
Thank you Rogan for your code. It helped me make a copy of my Input Stream. I changed it a little. Here's my version.

Couple of changes you could make. Make the byte array larger. I set it to 256, but put it to what ever makes sense. The read method returns an integer, but I'm calling it from the constructor, so the nothing is happening with the returned number. You could make this method public and call it and get the return, instead of calling it from the constructor.

Thanks Brian

Code:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class CopyInputStream
{
	private InputStream _is;
	private ByteArrayOutputStream _copy = new ByteArrayOutputStream();

	/**
	 * 
	 */
	public CopyInputStream(InputStream is)
	{
		_is = is;
		
		try
		{
			copy();
		}
		catch(IOException ex)
		{
			// do nothing
		}
	}

	private int copy() throws IOException
	{
		int read = 0;
		int chunk = 0;
		byte[] data = new byte[256];
		
		while(-1 != (chunk = _is.read(data)))
		{
			read += data.length;
			_copy.write(data, 0, chunk);
		}
		
		return read;
	}
	
	public InputStream getCopy()
	{
		return (InputStream)new ByteArrayInputStream(_copy.toByteArray());
	}
}

To call it

Code:
CopyInputStream cis = new CopyInputStream(input);
InputStream input1 = cis.getCopy();
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,732
Latest member
ArronPalin

Latest Threads

Top