About replication of InputStream streams

Source: Internet
Author: User

Today, because of the project needs, after acquiring a inputstream, it is possible to use it for read operations multiple times. Since the stream was read once, it could not be read again, so I had to think of something.

The InputStream object itself cannot replicate because it does not implement the Cloneable interface. At this point, you can first convert the InputStream into Bytearrayoutputstream, the latter to use InputStream objects, and then from the Bytearrayoutputstream conversion back to good. The code is implemented as follows:

[Java]View Plaincopyprint?
  1. InputStream input = Httpconn.getinputstream ();
  2. Bytearrayoutputstream BAOs = new Bytearrayoutputstream ();
  3. byte[] buffer = new byte[1024];
  4. int Len;
  5. while (len = input.read (buffer)) >-1) {
  6. Baos.write (buffer, 0, Len);
  7. }
  8. Baos.flush ();
  9. InputStream stream1 = new Bytearrayinputstream (Baos.tobytearray ());
  10. TODO: Show to foreground
  11. InputStream stream2 = new Bytearrayinputstream (Baos.tobytearray ());
  12. TODO: Local Cache
InputStream input =  httpconn.getinputstream ();            Bytearrayoutputstream BAOs = new Bytearrayoutputstream (); byte[] buffer = new Byte[1024];int len;while (len = Input.read (b Uffer)) >-1) {baos.write (buffer, 0, Len);} Baos.flush ();           InputStream stream1 = new Bytearrayinputstream (Baos.tobytearray ());//todo: Display to foreground inputstream stream2 = new Bytearrayinputstream (Baos.tobytearray ());//todo: Local cache

This applies to some streams that are not very large, because the cache stream consumes memory, and there is another way to use the mark and reset methods of the stream.
In fact, InputStream itself provides three interfaces: the first one, whether InputStream supports Mark, is not supported by default.
Java code
    1. Public Boolean marksupported () {
    2. return false;
    3. }
public boolean marksupported () {   return false;}
A second, Mark interface. The interface is implemented by default in InputStream without doing anything.
Java code
    1. Public synchronized void mark (int readlimit) {}
Public synchronized void mark (int readlimit) {}
A third, reset interface. The interface is implemented in InputStream, and the call throws an exception.
Java code
    1. Public synchronized Void Reset () throws IOException {
    2. throw New IOException ("Mark/reset not supported");
    3. }
Public synchronized void Reset () throws IOException {   throw new IOException (' Mark/reset not supported ');}
As you can see from the three interface definitions, first InputStream does not support mark, and the subclass needs to support that mark must override these three methods. The first interface is simple enough to indicate whether the InputStream supports mark. The official documentation for the Mark interface explains:"Marks the current position in this input stream.  Subsequent calls to the Reset method reposition the stream at the last mark, so that subsequent reads re-read the same bytes. The Readlimit parameter tells the input stream to allow many bytes to be read before the mark position expires.
Mark's general agreement is that if the method marksupported returns true, the input stream will always remember all bytes read after calling Mark, and whenever the method reset is called, it is ready to supply those same bytes again. However, if you can read more than Readlimit bytes from the stream before you call reset, you do not need the stream to remember any data at all. "

The official documentation for the Reset interface explains:relocate this stream to the location when the mark method was last called on this input stream. The general agreement for Reset is:
If the method marksupported returns True, the IOException may be thrown if the method mark has not been called since the stream was created, or the number of bytes read from the stream since the last call to mark is greater than the last parameter that was called by Mark. If such a ioexception is not thrown, the stream is reset to this state: all bytes read since the last call to mark (or, if Mark is not called) will be re-supplied to subsequent callers of the Read method, followed by a call to reset  All bytes of the next input data.  If the method marksupported returns false, the call to reset may throw IOException. If IOException is not thrown, the stream is reset to a fixed state that depends on the specific type of the input stream and the fixed state of how it was created.  The bytes provided to subsequent callers of the Read method depend on the specific type of input stream.

Simply put: The call to the Mark method will note the current time the Mark method is called, where InputStream is read. The reset method is called back to that location. To give a simple example:
Java code
  1. String content = "boycezhang!";
  2. InputStream InputStream = new Bytearrayinputstream (Content.getbytes ());
  3. Determine if the input stream supports the mark operation
  4. if (!inputstream.marksupported ()) {
  5. System.out.println ("Mark/reset not supported!");
  6. }
  7. int ch;
  8. Boolean marked = false;
  9. while ((ch = inputstream.read ())! =-1) {
  10. //read one character to output one character
  11. System.out.print ((char) ch);
  12. //Read to ' E ' when marked
  13. if ((char) ch = = ' e ') &!marked) {
  14. Inputstream.mark (Content.length ()); //Ignore Mark's parameters first
  15. marked = true;
  16. }
  17. //read '! ' Back to the marker position and start reading
  18. if (char) ch = = '! ' && marked) {
  19. Inputstream.reset ();
  20. marked = false;
  21. }
  22. }
  23. Program Final output: boycezhang! zhang!
String content = "boycezhang!"; Nputstream InputStream = new Bytearrayinputstream (Content.getbytes ());//determine if the input stream supports the Mark action if (! Inputstream.marksupported ()) {    System.out.println ("Mark/reset not supported!");} int ch;  Boolean marked = FALSE;  while ((ch = inputstream.read ())! =-1) {        //read one character output one character      System.out.print ((char) ch);      When reading ' E ', Mark     if ((char) ch = = ' E ') &!marked) {          Inputstream.mark (content.length ());  Just ignore Mark's argument         marked = true;       }                       Read '! ' When you return to the mark position, start reading      if ((char) ch = = '! ' && marked) {            inputstream.reset ();            marked = FALSE;      }  } Program Final output: boycezhang! zhang!
After looking at this example, we have a very intuitive understanding of the mark and reset interfaces. But what exactly is the parameter readlimit of the Mark interface? We know that InputStream does not support mark. To support the Mark subclass must rewrite these three methods, I want to say is different implementation subclass, Mark's parameters Readlimit effect is not the same. The common FileInputStream does not support mark. 1. For bufferedinputstream,readlimit: InputStream The Mark method is called, the position of the marker is valid until the Readlimit byte is read. If the number of bytes read is greater than readlimit, it may
In Bufferedinputstream's Read method source code, there is this paragraph:
Java code
    1. } else if  (buffer.length  >= marklimit)  {  
    2.      markpos =  -1;   /* buffer got too  big, invalidate mark */  
    3.      pos  = 0;        /*  drop buffer contents */  
    4.        else {             /* grow buffer */  
} else if (buffer.length >= marklimit) {     markpos =-1;   /* Buffer got too big, invalidate mark */     pos = 0;        /* Drop Buffer Contents */     } else {/            * Grow buffer */
Why is it possible
2. For another implementation class for InputStream: Bytearrayinputstream, we find that the Readlimit parameter is useless at all, and it doesn't matter how much is written when you call the Mark method.
Java code
    1. Public void mark (int readaheadlimit) {
    2. Mark = pos;
    3. }
    4. Public synchronized Void Reset () {
    5. pos = Mark;
    6. }
public void mark (int readaheadlimit) {   mark = pos;} Public synchronized void Reset () {   pos = mark;}


So because the mark and reset method mates can record and re-read the stream where we tagged the stream, a large part of it can solve some of our repetitive reading needs. The advantage of this approach is obvious: do not cache the entire InputStream data. There is not even any memory overhead for bytearrayinputstream. of course, this approach also has shortcomings: it is necessary to interfere with the InputStream reading details, but also relatively complex.

About replication of InputStream streams

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.