Mega Code Archive

 
Categories / Java / File Input Output
 

Size Limit InputStream

/*  * Input stream wrapper with a byte limit.  * Copyright (C) 2004 Stephen Ostermiller  * http://ostermiller.org/contact.pl?regarding=Java+Utilities  *  * This program is free software; you can redistribute it and/or modify  * it under the terms of the GNU General Public License as published by  * the Free Software Foundation; either version 2 of the License, or  * (at your option) any later version.  *  * This program is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * GNU General Public License for more details.  *  * See COPYING.TXT for details.  */ import java.io.*; /**  * An input stream wrapper that will read only a set number of bytes from the  * underlying stream.  *  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities  * @since ostermillerutils 1.04.00  */ public class SizeLimitInputStream extends InputStream {   /**    * The input stream that is being protected.    * All methods should be forwarded to it,    * after checking the size that has been read.    *    * @since ostermillerutils 1.04.00    */   protected InputStream in;   /**    * The number of bytes to read at most from this    * Stream.  Read methods should    * check to ensure that bytesRead never    * exceeds maxBytesToRead.    *    * @since ostermillerutils 1.04.00    */   protected long maxBytesToRead = 0;   /**    * The number of bytes that have been read    * from this stream.  Read methods should    * check to ensure that bytesRead never    * exceeds maxBytesToRead.    *    * @since ostermillerutils 1.04.00    */   protected long bytesRead = 0;   /**    * The number of bytes that have been read    * from this stream since mark() was called.    *    * @since ostermillerutils 1.04.00    */   protected long bytesReadSinceMark = 0;   /**    * The number of bytes the user has request    * to have been marked for reset.    *    * @since ostermillerutils 1.04.00    */   protected long markReadLimitBytes = -1;   /**    * Get the number of bytes actually read    * from this stream.    *    * @return number of bytes that have already been taken from this stream.    *    * @since ostermillerutils 1.04.00    */   public long getBytesRead(){     return bytesRead;   }   /**    * Get the maximum number of bytes left to read    * before the limit (set in the constructor) is reached.    *    * @return The number of bytes that (at a maximum) are left to be taken from this stream.    *    * @since ostermillerutils 1.04.00    */   public long getBytesLeft(){     return maxBytesToRead - bytesRead;   }   /**    * Tell whether the number of bytes specified    * in the constructor have been read yet.    *    * @return true iff the specified number of bytes have all been read.    *    * @since ostermillerutils 1.04.00    */   public boolean allBytesRead(){     return getBytesLeft() == 0;   }   /**    * Get the number of total bytes (including bytes already read)    * that can be read from this stream (as set in the constructor).    * @return Maximum bytes that can be read until the size limit runs out    *    * @since ostermillerutils 1.04.00    */   public long getMaxBytesToRead(){     return maxBytesToRead;   }   /**    * Create a new size limit input stream from    * another stream given a size limit.    *    * @param in The input stream.    * @param maxBytesToRead the max number of bytes to allow to be read from the underlying stream.    *    * @since ostermillerutils 1.04.00    */   public SizeLimitInputStream(InputStream in, long maxBytesToRead){     this.in = in;     this.maxBytesToRead = maxBytesToRead;   }   /**    * {@inheritDoc}    */   @Override public int read() throws IOException {     if (bytesRead >= maxBytesToRead){       return -1;     }     int b = in.read();     if(b != -1){       bytesRead++;       bytesReadSinceMark++;     }     return b;   }   /**    * {@inheritDoc}    */   @Override public int read(byte[] b) throws IOException {     return this.read(b, 0, b.length);   }   /**    * {@inheritDoc}    */   @Override public int read(byte[] b, int off, int len) throws IOException {     if (bytesRead >= maxBytesToRead){       return -1;     }     long bytesLeft = getBytesLeft();     if (len > bytesLeft){       len = (int)bytesLeft;     }     int bytesJustRead = in.read(b, off, len);     bytesRead += bytesJustRead;     bytesReadSinceMark += bytesJustRead;     return bytesJustRead;   }   /**    * {@inheritDoc}    */   @Override public long skip(long n) throws IOException {     if (bytesRead >= maxBytesToRead){       return -1;     }     long bytesLeft = getBytesLeft();     if (n > bytesLeft){       n = bytesLeft;     }     return in.skip(n);   }   /**    * {@inheritDoc}    */   @Override public int available() throws IOException {     int available = in.available();     long bytesLeft = getBytesLeft();     if (available > bytesLeft){       available = (int)bytesLeft;     }     return available;   }   /**    * Close this stream and underlying streams.    * Calling this method may make data on the    * underlying stream unavailable.    * <p>    * Consider wrapping this stream in a NoCloseStream    * so that clients can    * call close() with no effect.    *    * @since ostermillerutils 1.04.00    */   @Override public void close() throws IOException {     in.close();   }   /**    * {@inheritDoc}    */   @Override public void mark(int readlimit){     if (in.markSupported()){       markReadLimitBytes = readlimit;       bytesReadSinceMark = 0;       in.mark(readlimit);     }   }   /**    * {@inheritDoc}    */   @Override public void reset() throws IOException {     if (in.markSupported() && bytesReadSinceMark <= markReadLimitBytes){       bytesRead -= bytesReadSinceMark;       in.reset();       bytesReadSinceMark = 0;     }   }   /**    * {@inheritDoc}    */   @Override public boolean markSupported(){     return in.markSupported();   } }