I want to copy the "start" (i.e., first N characters) of an InputStream and then reset the stream to its start, so that it can be reused.
Using mark() and reset() does not work for all types of input streams, so I was wondering if there is a "generic" open source Java class (i.e., a stream wrapper) that can do th开发者_开发知识库is for any type of input stream.
Also, what would be the safest way of making the copy to avoid conversion errors?
Maybe you could wrap your InputStream in a PushbackInputStream
so you could read the first N bytes then unread()
them for reuse of the stream.
Take a look at how apache commons IOUtils copies stream IOUtils#copyLarge().
You can use populate ab ByteArrayInputStream
such a way.
byte[] buffer = new byte[n];
// n is the size from start- pupulate the buffer using technique from
IOUtils#copyLarge()
- create your ByteArrayInputStream using the
buffer
you created earlier
Here is the code snippet to IOUtils#copyLarge()
public static long copyLarge(InputStream input, OutputStream output)
throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
When it comes to reusing a stream and size doesn't matter (e.g. a few mega bytes), getting the byte[]
of the stream once, and then recreating ByteArrayInputStream
objects with the stored byte[]
when necessary has always worked for me. No more trouble with mark()
and reset()
.
After quite a bit of experimentation, it seems that the best (although imperfect) approach is to use the mark() and reset() methods of the InputStream.
If the original stream does not support marking/resetting, an easy workaround is to wrap it inside a BufferedInputStream.*
精彩评论