Java/File Input Output/InputStream

Материал из Java эксперт
Перейти к: навигация, поиск

An input stream which reads sequentially from multiple sources

   <source lang="java">
 

/*

* 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.*; import java.util.ArrayList; /**

* An input stream which reads sequentially from multiple sources.
* More information about this class is available from .
*
* @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
* @since ostermillerutils 1.04.00
*/

public class ConcatInputStream extends InputStream {

 /**
  * Current index to inputStreamQueue
  *
  * @since ostermillerutils 1.04.01
  */
 private int inputStreamQueueIndex = 0;
 /**
  * Queue of inputStreams that have yet to be read from.
  *
  * @since ostermillerutils 1.04.01
  */
 private ArrayList<InputStream> inputStreamQueue = new ArrayList<InputStream>();
 /**
  * A cache of the current inputStream from the inputStreamQueue
  * to avoid unneeded access to the queue which must
  * be synchronized.
  *
  * @since ostermillerutils 1.04.01
  */
 private InputStream currentInputStream = null;
 /**
  * true iff the client may add more inputStreams.
  *
  * @since ostermillerutils 1.04.01
  */
 private boolean doneAddingInputStreams = false;
 /**
  * Causes the addInputStream method to throw IllegalStateException
  * and read() methods to return -1 (end of stream)
  * when there is no more available data.
*

* Calling this method when this class is no longer accepting * more inputStreams has no effect. * * @since ostermillerutils 1.04.01 */ public void lastInputStreamAdded(){ doneAddingInputStreams = true; } /** * Add the given inputStream to the queue of inputStreams from which to * concatenate data. * * @param in InputStream to add to the concatenation. * @throws IllegalStateException if more inputStreams can"t be added because lastInputStreamAdded() has been called, close() has been called, or a constructor with inputStream parameters was used. * * @since ostermillerutils 1.04.01 */ public void addInputStream(InputStream in){ synchronized(inputStreamQueue){ if (in == null) throw new NullPointerException(); if (closed) throw new IllegalStateException("ConcatInputStream has been closed"); if (doneAddingInputStreams) throw new IllegalStateException("Cannot add more inputStreams - the last inputStream has already been added."); inputStreamQueue.add(in); } } /** * Add the given inputStream to the queue of inputStreams from which to * concatenate data. * * @param in InputStream to add to the concatenation. * @throws IllegalStateException if more inputStreams can"t be added because lastInputStreamAdded() has been called, close() has been called, or a constructor with inputStream parameters was used. * @throws NullPointerException the array of inputStreams, or any of the contents is null. * * @since ostermillerutils 1.04.01 */ public void addInputStreams(InputStream[] in){ for (InputStream element: in) { addInputStream(element); } } /** * Gets the current inputStream, looking at the next * one in the list if the current one is null. * * @since ostermillerutils 1.04.01 */ private InputStream getCurrentInputStream(){ if (currentInputStream == null && inputStreamQueueIndex < inputStreamQueue.size()){ synchronized(inputStreamQueue){ // inputStream queue index is advanced only by the nextInputStream() // method. Don"t do it here. currentInputStream = inputStreamQueue.get(inputStreamQueueIndex); } } return currentInputStream; } /** * Indicate that we are done with the current inputStream and we should * advance to the next inputStream. * * @since ostermillerutils 1.04.01 */ private void advanceToNextInputStream(){ currentInputStream = null; inputStreamQueueIndex++; } /** * True iff this the close() method has been called on this stream. * * @since ostermillerutils 1.04.00 */ private boolean closed = false; /** * Create a new input stream that can dynamically accept new sources. * <p> * New sources should be added using the addInputStream() method. * When all sources have been added the lastInputStreamAdded() should * be called so that read methods can return -1 (end of stream). * <p> * Adding new sources may by interleaved with read calls. * * @since ostermillerutils 1.04.01 */ public ConcatInputStream(){ // Empty constructor } /** * Create a new InputStream with one source. * * @param in InputStream to use as a source. * * @throws NullPointerException if in is null * * @since ostermillerutils 1.04.00 */ public ConcatInputStream(InputStream in){ addInputStream(in); lastInputStreamAdded(); } /** * Create a new InputStream with two sources. * * @param in1 first InputStream to use as a source. * @param in2 second InputStream to use as a source. * * @throws NullPointerException if either source is null. * * @since ostermillerutils 1.04.00 */ public ConcatInputStream(InputStream in1, InputStream in2){ addInputStream(in1); addInputStream(in2); lastInputStreamAdded(); } /** * Create a new InputStream with an arbitrary number of sources. * * @param in InputStreams to use as a sources. * * @throws NullPointerException if the input array on any element is null. * * @since ostermillerutils 1.04.00 */ public ConcatInputStream(InputStream[] in){ addInputStreams(in); lastInputStreamAdded(); } /** * Reads the next byte of data from the underlying streams. The value byte is * returned as an int in the range 0 to 255. If no byte is available because * the end of the stream has been reached, the value -1 is returned. This method * blocks until input data is available, the end of the stream is detected, or * an exception is thrown. * <p> * If this class in not done accepting inputstreams and the end of the last known * stream is reached, this method will block forever unless another thread * adds an inputstream or interrupts. * * @return the next byte of data, or -1 if the end of the stream is reached. * * @throws IOException if an I/O error occurs. */ @Override public int read() throws IOException { if (closed) throw new IOException("InputStream closed"); int r = -1; while (r == -1){ InputStream in = getCurrentInputStream(); if (in == null){ if (doneAddingInputStreams) return -1; try { Thread.sleep(100); } catch (InterruptedException iox){ throw new IOException("Interrupted"); } } else { r = in.read(); if (r == -1) advanceToNextInputStream(); } } return r; } /** * Reads some number of bytes from the underlying streams and stores them into * the buffer array b. The number of bytes actually read is returned as an * integer. This method blocks until input data is available, end of file is * detected, or an exception is thrown. * <p> * If the length of b is zero, * then no bytes are read and 0 is returned; otherwise, there is an attempt * to read at least one byte. * <p> * The read(b) method for class InputStream has the same effect as:
* read(b, 0, b.length) * <p> * If this class in not done accepting inputstreams and the end of the last known * stream is reached, this method will block forever unless another thread * adds an inputstream or interrupts. * * @param b - Destination buffer * @return The number of bytes read, or -1 if the end of the stream has been reached * * @throws IOException - If an I/O error occurs * @throws NullPointerException - If b is null. * * @since ostermillerutils 1.04.00 */ @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } /** * Reads up to length bytes of data from the underlying streams into an array of bytes. * An attempt is made to read as many as length bytes, but a smaller number may be read, * possibly zero. The number of bytes actually read is returned as an integer. * <p> * If length is zero, * then no bytes are read and 0 is returned; otherwise, there is an attempt * to read at least one byte. * <p> * This method blocks until input data is available * <p> * If this class in not done accepting inputstreams and the end of the last known * stream is reached, this method will block forever unless another thread * adds an inputstream or interrupts. * * @param b Destination buffer * @param off Offset at which to start storing bytes * @param len Maximum number of bytes to read * @return The number of bytes read, or -1 if the end of the stream has been reached * * @throws IOException - If an I/O error occurs * @throws NullPointerException - If b is null. * @throws IndexOutOfBoundsException - if length or offset are not possible. */ @Override public int read(byte[] b, int off, int len) throws IOException { if (off < 0 || len < 0 || off + len > b.length) throw new IllegalArgumentException(); if (closed) throw new IOException("InputStream closed"); int r = -1; while (r == -1){ InputStream in = getCurrentInputStream(); if (in == null){ if (doneAddingInputStreams) return -1; try { Thread.sleep(100); } catch (InterruptedException iox){ throw new IOException("Interrupted"); } } else { r = in.read(b, off, len); if (r == -1) advanceToNextInputStream(); } } return r; } /** * Skips over and discards n bytes of data from this input stream. The skip method * may, for a variety of reasons, end up skipping over some smaller number of bytes, * possibly 0. This may result from any of a number of conditions; reaching end of * file before n bytes have been skipped is only one possibility. The actual number * of bytes skipped is returned. If n is negative, no bytes are skipped. * <p> * If this class in not done accepting inputstreams and the end of the last known * stream is reached, this method will block forever unless another thread * adds an inputstream or interrupts. * * @param n he number of characters to skip * @return The number of characters actually skipped * * @throws IOException If an I/O error occurs * * @since ostermillerutils 1.04.00 */ @Override public long skip(long n) throws IOException { if (closed) throw new IOException("InputStream closed"); if (n <= 0) return 0; long s = -1; while (s <= 0){ InputStream in = getCurrentInputStream(); if (in == null){ if (doneAddingInputStreams) return 0; try { Thread.sleep(100); } catch (InterruptedException iox){ throw new IOException("Interrupted"); } } else { s = in.skip(n); // When nothing was skipped it is a bit of a puzzle. // The most common cause is that the end of the underlying // stream was reached. In which case calling skip on it // will always return zero. If somebody were calling skip // until it skipped everything they needed, there would // be an infinite loop if we were to return zero here. // If we get zero, let us try to read one character so // we can see if we are at the end of the stream. If so, // we will move to the next. if (s <= 0) { // read() will advance to the next stream for us, so don"t do it again s = ((read()==-1)?-1:1); } } } return s; } /** * Returns the number of bytes that can be read (or skipped over) from this input * stream without blocking by the next caller of a method for this input stream. * The next caller might be the same thread or or another thread. * * @throws IOException If an I/O error occurs * * @since ostermillerutils 1.04.00 */ @Override public int available() throws IOException { if (closed) throw new IOException("InputStream closed"); InputStream in = getCurrentInputStream(); if (in == null) return 0; return in.available(); } /** * Closes this input stream and releases any system resources associated with the stream. * * @since ostermillerutils 1.04.00 */ @Override public void close() throws IOException { if (closed) return; for (Object element: inputStreamQueue) { ((InputStream)element).close(); } closed = true; } /** * Mark not supported * * @since ostermillerutils 1.04.00 */ @Override public void mark(int readlimit){ // Mark not supported -- do nothing } /** * Reset not supported. * * @throws IOException because reset is not supported. * * @since ostermillerutils 1.04.00 */ @Override public void reset() throws IOException { throw new IOException("Reset not supported"); } /** * Does not support mark. * * @return false * * @since ostermillerutils 1.04.00 */ @Override public boolean markSupported(){ return false; } } </source>

An limited-data-size input stream

   <source lang="java">
    

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream;

/**

* An input stream, which limits its data size. This stream is
* used, if the content length is unknown.
*/

public abstract class LimitedInputStream

       extends FilterInputStream {
   /**
    * The maximum size of an item, in bytes.
    */
   private long sizeMax;
   /**
    * The current number of bytes.
    */
   private long count;
   /**
    * Whether this stream is already closed.
    */
   private boolean closed;
   /**
    * Creates a new instance.
    * @param pIn The input stream, which shall be limited.
    * @param pSizeMax The limit; no more than this number of bytes
    *   shall be returned by the source stream.
    */
   public LimitedInputStream(InputStream pIn, long pSizeMax) {
       super(pIn);
       sizeMax = pSizeMax;
   }
   /**
    * Called to indicate, that the input streams limit has
    * been exceeded.
    * @param pSizeMax The input streams limit, in bytes.
    * @param pCount The actual number of bytes.
    * @throws IOException The called method is expected
    *   to raise an IOException.
    */
   protected abstract void raiseError(long pSizeMax, long pCount)
           throws IOException;
   /** Called to check, whether the input streams
    * limit is reached.
    * @throws IOException The given limit is exceeded.
    */
   private void checkLimit() throws IOException {
       if (count > sizeMax) {
           raiseError(sizeMax, count);
       }
   }
   /**
    * Reads the next byte of data from this input stream. The value
    * byte is returned as an int in the range
    * 0 to 255. If no byte is available
    * because the end of the stream has been reached, the value
    * -1 is returned. This method blocks until input data
    * is available, the end of the stream is detected, or an exception
    * is thrown.
    * <p>
    * This method
    * simply performs in.read() and returns the result.
    *
    * @return     the next byte of data, or -1 if the end of the
    *             stream is reached.
    * @exception  IOException  if an I/O error occurs.
    * @see        java.io.FilterInputStream#in
    */
   public int read() throws IOException {
       int res = super.read();
       if (res != -1) {
           count++;
           checkLimit();
       }
       return res;
   }
   /**
    * Reads up to len bytes of data from this input stream
    * into an array of bytes. If len is not zero, the method
    * blocks until some input is available; otherwise, no
    * bytes are read and 0 is returned.
    * <p>
    * This method simply performs in.read(b, off, len)
    * and returns the result.
    *
    * @param      b     the buffer into which the data is read.
    * @param      off   The start offset in the destination array
    *                   b.
    * @param      len   the maximum number of bytes read.
    * @return     the total number of bytes read into the buffer, or
    *             -1 if there is no more data because the end of
    *             the stream has been reached.
    * @exception  NullPointerException If b is null.
    * @exception  IndexOutOfBoundsException If off is negative,
    * len is negative, or len is greater than
    * b.length - off
    * @exception  IOException  if an I/O error occurs.
    * @see        java.io.FilterInputStream#in
    */
   public int read(byte[] b, int off, int len) throws IOException {
       int res = super.read(b, off, len);
       if (res > 0) {
           count += res;
           checkLimit();
       }
       return res;
   }
   /**
    * Returns, whether this stream is already closed.
    * @return True, if the stream is closed, otherwise false.
    * @throws IOException An I/O error occurred.
    */
   public boolean isClosed() throws IOException {
       return closed;
   }
   /**
    * Closes this input stream and releases any system resources
    * associated with the stream.
    * This
    * method simply performs in.close().
    *
    * @exception  IOException  if an I/O error occurs.
    * @see        java.io.FilterInputStream#in
    */
   public void close() throws IOException {
       closed = true;
       super.close();
   }

}



 </source>
   
  
 
  



A trace of the data that is being retrieved from an input stream

   <source lang="java">

/*

* The contents of this file are subject to the terms 
* of the Common Development and Distribution License 
* (the "License").  You may not use this file except 
* in compliance with the License.
* 
* You can obtain a copy of the license at 
* glassfish/bootstrap/legal/CDDLv1.0.txt or 
* https://glassfish.dev.java.net/public/CDDLv1.0.html. 
* See the License for the specific language governing 
* permissions and limitations under the License.
* 
* When distributing Covered Code, include this CDDL 
* HEADER in each file and include the License file at 
* glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable, 
* add the following below this CDDL HEADER, with the 
* fields enclosed by brackets "[]" replaced with your 
* own identifying information: Portions Copyright [yyyy] 
* [name of copyright owner]
*/

/*

* @(#)TraceInputStream.java  1.7 05/08/29
*
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
*/

//Revised from sun mail util import java.io.*; /**

* This class is a FilterInputStream that writes the bytes
* being read from the given input stream into the given output
* stream. This class is typically used to provide a trace of
* the data that is being retrieved from an input stream.
*
* @author John Mani
*/

public class TraceInputStream extends FilterInputStream {

   private boolean trace = false;
   private boolean quote = false;
   private OutputStream traceOut;
   /**
    * Creates an input stream filter built on top of the specified
    * input stream.
    *   
    * @param   in   the underlying input stream.
    * @param   out  the trace stream
    */
   public TraceInputStream(InputStream in, OutputStream traceOut) {
 super(in);
 this.traceOut = traceOut;
   }
   /**
    * Set trace mode.
    * @param trace the trace mode
    */
   public void setTrace(boolean trace) {
 this.trace = trace;
   }
   /**
    * Set quote mode.
    * @param quote the quote mode
    */
   public void setQuote(boolean quote) {
 this.quote = quote;
   }
   /**
    * Reads the next byte of data from this input stream. Returns
    * -1 if no data is available. Writes out the read
    * byte into the trace stream, if trace mode is true
    */
   public int read() throws IOException {
 int b = in.read();
 if (trace && b != -1) {
     if (quote)
   writeByte(b);
     else
   traceOut.write(b);
 }
 return b;
   }
   /**
    * Reads up to len bytes of data from this input stream
    * into an array of bytes. Returns -1 if no more data
    * is available. Writes out the read bytes into the trace stream, if 
    * trace mode is true
    */
   public int read(byte b[], int off, int len) throws IOException {
 int count = in.read(b, off, len);
 if (trace && count != -1) {
     if (quote) {
   for (int i = 0; i < count; i++)
       writeByte(b[off + i]);
     } else
   traceOut.write(b, off, count);
 }
 return count;
   }
   /**
    * Write a byte in a way that every byte value is printable ASCII.
    */
   private final void writeByte(int b) throws IOException {
 b &= 0xff;
 if (b > 0x7f) {
     traceOut.write("M");
     traceOut.write("-");
     b &= 0x7f;
 }
 if (b == "\r") {
     traceOut.write("\\");
     traceOut.write("r");
 } else if (b == "\n") {
     traceOut.write("\\");
     traceOut.write("n");
     traceOut.write("\n");
 } else if (b == "\t") {
     traceOut.write("\\");
     traceOut.write("t");
 } else if (b < " ") {
     traceOut.write("^");
     traceOut.write("@" + b);
 } else {
     traceOut.write(b);
 }
   }

}

 </source>
   
  
 
  



Combined InputStream

   <source lang="java">
 

/**

* Project pack:tag >> http://packtag.sf.net
*
* This software is published under the terms of the LGPL
* License version 2.1, a copy of which has been included with this
* distribution in the "lgpl.txt" file.
* 
* Creation date: 15.04.2007 - 18:27:26
* Last author:   $Author: danielgalan $
* Last modified: $Date: 2008/02/10 20:03:21 $
* Revision:      $Revision: 1.4 $
* 
* $Log: CombinedInputStream.java,v $
* Revision 1.4  2008/02/10 20:03:21  danielgalan
* Fix for IE - if after a closing bracket a var keyword is, IE can"t interpret this, eg "varx={}var y ={}" mus be seperated: "varx={}\nvar y ={}"
*
* Revision 1.3  2007/05/02 21:38:38  danielgalan
* alias to name
*
* Revision 1.2  2007/05/02 21:29:18  danielgalan
* last fixes for 2.0, attribute media
*
* Revision 1.1  2007/04/22 19:04:24  danielgalan
* pack.tag moved from subversion to good old CVS
*/

import java.io.IOException; import java.io.InputStream;

/**

* Reads multiple Inputstreams as one
* 
* @author  Daniel Galán y Martins
* @version $Revision: 1.4 $
*/

public class CombinedInputStream extends InputStream {

 /** The current Stream to read from */
 private int current;
 boolean isNextLineFeed = false;
 /** The Streams to combine */
 private final InputStream[] streams;
 /**
  * Constructs an combined InputStream, that reads from array stream per stream, till the last stream
  * 
  * @param streams All Streams that will be combined
  */
 public CombinedInputStream(final InputStream[] streams) {
   current = 0;
   this.streams = streams;
 }
 /**
  * Reads from the list of streams, when the last stream is over, -1 will be returned (as usual)
  */
 public int read() throws IOException {
   if (isNextLineFeed) {
     isNextLineFeed = false;
     return "\n";
   }
   int i = -1;
   if (current < streams.length) {
     i = streams[current].read();
     if (i == -1) {
       isNextLineFeed = true;
       // the current stream has been finished, use the next one
       current++;
       return read();
     }
   }
   return i;
 }
 /** Closes all streams */
 public void close() throws IOException {
   for (int i = 0; i < streams.length; i++) {
     streams[i].close();
   }
 }
 /** Is there more data to read */
 public int available() throws IOException {
   return current < streams.length ? streams[current].available() : 0;
 }

}


 </source>
   
  
 
  



Compare two InputStream

   <source lang="java">
 

/*

* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of 
* individual contributors. 
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.util.Arrays; /**

* @author Randall Hauch
*/

public class Main {

 /**
  * Compare two input stream
  * 
  * @param input1 the first stream
  * @param input2 the second stream
  * @return true if the streams contain the same content, or false otherwise
  * @throws IOException
  * @throws IllegalArgumentException if the stream is null
  */
 public static boolean isSame( InputStream input1,
                               InputStream input2 ) throws IOException {
     boolean error = false;
     try {
         byte[] buffer1 = new byte[1024];
         byte[] buffer2 = new byte[1024];
         try {
             int numRead1 = 0;
             int numRead2 = 0;
             while (true) {
                 numRead1 = input1.read(buffer1);
                 numRead2 = input2.read(buffer2);
                 if (numRead1 > -1) {
                     if (numRead2 != numRead1) return false;
                     // Otherwise same number of bytes read
                     if (!Arrays.equals(buffer1, buffer2)) return false;
                     // Otherwise same bytes read, so continue ...
                 } else {
                     // Nothing more in stream 1 ...
                     return numRead2 < 0;
                 }
             }
         } finally {
             input1.close();
         }
     } catch (IOException e) {
         error = true; // this error should be thrown, even if there is an error closing stream 2
         throw e;
     } catch (RuntimeException e) {
         error = true; // this error should be thrown, even if there is an error closing stream 2
         throw e;
     } finally {
         try {
             input2.close();
         } catch (IOException e) {
             if (!error) throw e;
         }
     }
 }

}


 </source>
   
  
 
  



Convert InputStream to String

   <source lang="java">
   

import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class Main {

 public static void main(String[] args) throws Exception {
   InputStream is = Main.class.getResourceAsStream("/data.txt");
   System.out.println(convertStreamToString(is));
 }
 public static String convertStreamToString(InputStream is) throws Exception {
   BufferedReader reader = new BufferedReader(new InputStreamReader(is));
   StringBuilder sb = new StringBuilder();
   String line = null;
   while ((line = reader.readLine()) != null) {
     sb.append(line + "\n");
   }
   is.close();
   return sb.toString();
 }

}



 </source>
   
  
 
  



Convert Reader to InputStream

   <source lang="java">

/*

* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License.  When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/

import java.io.*;

/**

  • This class convert Reader to InputStream. It works by converting
  • the characters to the encoding specified in constructor parameter.
  • @author Petr Hamernik, David Strupl
  • /

public class ReaderInputStream extends InputStream {

   /** Input Reader class. */
   private Reader reader;
   private PipedOutputStream pos;
   private PipedInputStream pis;
   private OutputStreamWriter osw;
   /** Creates new input stream from the given reader.
    * Uses the platform default encoding.
   * @param reader Input reader
   */
   public ReaderInputStream(Reader reader) throws IOException {
       this.reader = reader;
       pos = new PipedOutputStream();
       pis = new PipedInputStream(pos);
       osw = new OutputStreamWriter(pos);
   }
   /** Creates new input stream from the given reader and encoding.
    * @param reader Input reader
    * @param encoding
    */
   public ReaderInputStream(Reader reader, String encoding)
   throws IOException {
       this.reader = reader;
       pos = new PipedOutputStream();
       pis = new PipedInputStream(pos);
       osw = new OutputStreamWriter(pos, encoding);
   }
   public int read() throws IOException {
       if (pis.available() > 0) {
           return pis.read();
       }
       int c = reader.read();
       if (c == -1) {
           return c;
       }
       osw.write(c);
       osw.flush();
       pos.flush();
       return pis.read();
   }
   public int read(byte[] b, int off, int len) throws IOException {
       if (len == 0) {
           return 0;
       }
       int c = read();
       if (c == -1) {
           return -1;
       }
       b[off] = (byte) c;
       int i = 1;
       // Don"t try to fill up the buffer if the reader is waiting.
       for (; (i < len) && reader.ready(); i++) {
           c = read();
           if (c == -1) {
               return i;
           }
           b[off + i] = (byte) c;
       }
       return i;
   }
   public int available() throws IOException {
       int i = pis.available();
       if (i > 0) {
           return i;
       }
       if (reader.ready()) {
           // Char must produce at least one byte.
           return 1;
       } else {
           return 0;
       }
   }
   public void close() throws IOException {
       reader.close();
       osw.close();
       pis.close();
   }

}

 </source>
   
  
 
  



Creating a Manifest for a JAR File

   <source lang="java">
   

import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.util.jar.Manifest; public class Main {

 public static void main(String[] argv) throws Exception {
   // Create a manifest from a file
   InputStream fis = new FileInputStream("manifestfile");
   Manifest manifest = new Manifest(fis);
   // Construct a string version of a manifest
   StringBuffer sbuf = new StringBuffer();
   sbuf.append("Manifest-Version: 1.0\n");
   sbuf.append("\n");
   sbuf.append("Name: javax/swing/JScrollPane.class\n");
   sbuf.append("Java-Bean: True\n");
   // Convert the string to a input stream
   InputStream is = new ByteArrayInputStream(sbuf.toString().getBytes("UTF-8"));
   // Create the manifest
   manifest = new Manifest(is);
 }

}



 </source>
   
  
 
  



Creating an input or output stream on a ByteBuffer

   <source lang="java">
   

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; public class Main {

 public static void main(String[] argv) throws Exception {
   ByteBuffer buf = ByteBuffer.allocate(10);
   OutputStream os = new ByteBufferBackedOutputStream(buf);
   InputStream is = new  ByteBufferBackedInputStream(buf);
 }

} class ByteBufferBackedInputStream extends InputStream{

 ByteBuffer buf;
 ByteBufferBackedInputStream( ByteBuffer buf){
   this.buf = buf;
 }
 public synchronized int read() throws IOException {
   if (!buf.hasRemaining()) {
     return -1;
   }
   return buf.get();
 }
 public synchronized int read(byte[] bytes, int off, int len) throws IOException {
   len = Math.min(len, buf.remaining());
   buf.get(bytes, off, len);
   return len;
 }

} class ByteBufferBackedOutputStream extends OutputStream{

 ByteBuffer buf;
 ByteBufferBackedOutputStream( ByteBuffer buf){
   this.buf = buf;
 }
 public synchronized void write(int b) throws IOException {
   buf.put((byte) b);
 }
 public synchronized void write(byte[] bytes, int off, int len) throws IOException {
   buf.put(bytes, off, len);
 }
 

}



 </source>
   
  
 
  



Deserializes an object from an input stream.

   <source lang="java">
 

/*

* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
* 
*      http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream;

public class Main {

 /**
  * This method deserializes an object from an input stream.
  *
  * @param file The input file
  * @return The deserialized object
  * @exception IOException IOError
  */
 public static Object deserializeObject(File file)
 throws IOException, ClassNotFoundException {
     FileInputStream fis = new FileInputStream(file);
     Object object = null;
     try {
         ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(fis));
         object = ois.readObject();
     } finally {
         fis.close();
     }
     return object;
 }

}


 </source>
   
  
 
  



EOLConvertingInputStream: InputStream which converts \r bytes not followed by \n and \n not preceded by \r to \r\n.

   <source lang="java">

/****************************************************************

* Licensed to the Apache Software Foundation (ASF) under one   *
* or more contributor license agreements.  See the NOTICE file *
* distributed with this work for additional information        *
* regarding copyright ownership.  The ASF licenses this file   *
* to you under the Apache License, Version 2.0 (the            *
* "License"); you may not use this file except in compliance   *
* with the License.  You may obtain a copy of the License at   *
*                                                              *
*   http://www.apache.org/licenses/LICENSE-2.0                 *
*                                                              *
* Unless required by applicable law or agreed to in writing,   *
* software distributed under the License is distributed on an  *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
* KIND, either express or implied.  See the License for the    *
* specific language governing permissions and limitations      *
* under the License.                                           *
****************************************************************/

import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; /**

* InputStream which converts \r
* bytes not followed by \n and \n not 
* preceded by \r to \r\n.
*/

public class EOLConvertingInputStream extends InputStream {

   /** Converts single "\r" to "\r\n" */
   public static final int CONVERT_CR   = 1;
   /** Converts single "\n" to "\r\n" */
   public static final int CONVERT_LF   = 2;
   /** Converts single "\r" and "\n" to "\r\n" */
   public static final int CONVERT_BOTH = 3;
   
   private PushbackInputStream in = null;
   private int previous = 0;
   private int flags = CONVERT_BOTH;
   
   /**
    * Creates a new EOLConvertingInputStream
    * instance converting bytes in the given InputStream.
    * The flag CONVERT_BOTH is the default.
    * 
    * @param in the InputStream to read from.
    */
   public EOLConvertingInputStream(InputStream in) {
       this(in, CONVERT_BOTH);
   }
   /**
    * Creates a new EOLConvertingInputStream
    * instance converting bytes in the given InputStream.
    * 
    * @param in the InputStream to read from.
    * @param flags one of CONVERT_CR, CONVERT_LF or
    *        CONVERT_BOTH.
    */
   public EOLConvertingInputStream(InputStream in, int flags) {
       super();
       
       this.in = new PushbackInputStream(in, 2);
       this.flags = flags;
   }
   /**
    * Closes the underlying stream.
    * 
    * @throws IOException on I/O errors.
    */
   @Override
   public void close() throws IOException {
       in.close();
   }
   
   /**
    * @see java.io.InputStream#read()
    */
   @Override
   public int read() throws IOException {
       int b = in.read();
       
       if (b == -1) {
           return -1;
       }
       
       if ((flags & CONVERT_CR) != 0 && b == "\r") {
           int c = in.read();
           if (c != -1) {
               in.unread(c);
           }
           if (c != "\n") {
               in.unread("\n");
           }
       } else if ((flags & CONVERT_LF) != 0 && b == "\n" && previous != "\r") {
           b = "\r";
           in.unread("\n");
       }
       
       previous = b;
       
       return b;
   }

}

 </source>
   
  
 
  



Minimal InputStream subclass to fetch bytes form a String

   <source lang="java">
 

/* Copyright (c) 2001-2009, The HSQL Development Group

* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.io.IOException; import java.io.InputStream; /**

* minimal InputStream subclass to fetch bytes form a String
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 1.7.0
*/

public class StringInputStream extends InputStream {

   protected int    strOffset  = 0;
   protected int    charOffset = 0;
   protected int    available;
   protected String str;
   public StringInputStream(String s) {
       str       = s;
       available = s.length() * 2;
   }
   public int read() throws java.io.IOException {
       if (available == 0) {
           return -1;
       }
       available--;
       char c = str.charAt(strOffset);
       if (charOffset == 0) {
           charOffset = 1;
           return (c & 0x0000ff00) >> 8;
       } else {
           charOffset = 0;
           strOffset++;
           return c & 0x000000ff;
       }
   }
   public int available() throws IOException {
       return available;
   }

}


 </source>
   
  
 
  



Read and return the entire contents of the supplied InputStream.

   <source lang="java">
 

/*

* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of 
* individual contributors. 
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; /**

* @author Randall Hauch
*/

public class Main {

 /**
  * Read and return the entire contents of the supplied {@link InputStream stream}. This method always closes the stream when
  * finished reading.
  * 
  * @param stream the stream to the contents; may be null
  * @return the contents, or an empty byte array if the supplied reader is null
  * @throws IOException if there is an error reading the content
  */
 public static byte[] readBytes( InputStream stream ) throws IOException {
     if (stream == null) return new byte[] {};
     byte[] buffer = new byte[1024];
     ByteArrayOutputStream output = new ByteArrayOutputStream();
     boolean error = false;
     try {
         int numRead = 0;
         while ((numRead = stream.read(buffer)) > -1) {
             output.write(buffer, 0, numRead);
         }
     } catch (IOException e) {
         error = true; // this error should be thrown, even if there is an error closing stream
         throw e;
     } catch (RuntimeException e) {
         error = true; // this error should be thrown, even if there is an error closing stream
         throw e;
     } finally {
         try {
             stream.close();
         } catch (IOException e) {
             if (!error) throw e;
         }
     }
     output.flush();
     return output.toByteArray();
 }

}


 </source>
   
  
 
  



Read and return the entire contents of the supplied InputStream. This method always closes the stream when finished reading.

   <source lang="java">
 

/*

* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of 
* individual contributors. 
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; /**

* @author Randall Hauch
*/

public class Main {

 /**
  * Read and return the entire contents of the supplied {@link InputStream}. This method always closes the stream when finished
  * reading.
  * 
  * @param stream the streamed contents; may be null
  * @return the contents, or an empty string if the supplied stream is null
  * @throws IOException if there is an error reading the content
  */
 public static String read( InputStream stream ) throws IOException {
     return stream == null ? "" : read(new InputStreamReader(stream));
 }
 /**
  * Read and return the entire contents of the supplied {@link Reader}. This method always closes the reader when finished
  * reading.
  * 
  * @param reader the reader of the contents; may be null
  * @return the contents, or an empty string if the supplied reader is null
  * @throws IOException if there is an error reading the content
  */
 public static String read( Reader reader ) throws IOException {
     if (reader == null) return "";
     StringBuilder sb = new StringBuilder();
     boolean error = false;
     try {
         int numRead = 0;
         char[] buffer = new char[1024];
         while ((numRead = reader.read(buffer)) > -1) {
             sb.append(buffer, 0, numRead);
         }
     } catch (IOException e) {
         error = true; // this error should be thrown, even if there is an error closing reader
         throw e;
     } catch (RuntimeException e) {
         error = true; // this error should be thrown, even if there is an error closing reader
         throw e;
     } finally {
         try {
             reader.close();
         } catch (IOException e) {
             if (!error) throw e;
         }
     }
     return sb.toString();
 }

}


 </source>
   
  
 
  



Reads at most certain bytes from input stream and returns them as a byte array.

   <source lang="java">
 

/*

* Copyright Aduna (http://www.aduna-software.ru/) (c) 1997-2006.
*
* Licensed under the Aduna BSD-style license.
*/

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class Main {

 /**
  * Reads at most maxBytes bytes from the supplied input stream and
  * returns them as a byte array.
  *
  * @param in The InputStream supplying the bytes.
  * @param maxBytes The maximum number of bytes to read from the input
  * stream.
  * @return A byte array of size maxBytes if the input stream can
  * produce that amount of bytes, or a smaller byte containing all available
  * bytes from the stream otherwise.
  */
 public static final byte[] readBytes(InputStream in, int maxBytes)
   throws IOException
 {
   byte[] result = new byte[maxBytes];
   int bytesRead = in.read(result);
   int totalBytesRead = bytesRead;
   while (totalBytesRead < maxBytes && bytesRead >= 0) {
     // Read more bytes
     bytesRead = in.read(result, bytesRead, maxBytes - bytesRead);
     if (bytesRead > 0) {
       totalBytesRead += bytesRead;
     }
   }
   if (totalBytesRead < 0) {
     // InputStream at end-of-file
     result = new byte[0];
   }
   else if (totalBytesRead < maxBytes) {
     // Create smaller byte array
     byte[] tmp = new byte[totalBytesRead];
     System.arraycopy(result, 0, tmp, 0, totalBytesRead);
     result = tmp;
   }
   return result;
 }

}


 </source>
   
  
 
  



Size Limit InputStream

   <source lang="java">
 

/*

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

}


 </source>