a .NET library that can read/write Office formats without Microsoft Office installed. No COM+, no interop.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

389 lines
17 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace NPOI.Util
{
/// <summary>
/// This abstract class is the superclass of all classes representing
/// an input stream of bytes.
/// <para> Applications that need to define a subclass of <see cref="InputStream"/>
/// must always provide a method that returns the next byte of input.</para>
/// </summary>
/// <seealso cref="System.IO.Stream" />
public abstract class InputStream : Stream
{
// MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to
// use when skipping.
private static int MAX_SKIP_BUFFER_SIZE = 2048;
/// <summary>
/// Reads the next byte of data from the input stream. The value byte is
/// returned as an <c>int</c> in the range <c>0</c> to
/// <c>255</c>. If no byte is available because the end of the stream
/// has been reached, the value <c>-1</c> is returned. This method
/// blocks until input data is available, the end of the stream is detected,
/// or an exception is thrown.
///
/// A subclass must provide an implementation of this method.
/// </summary>
/// <returns>
/// the next byte of data, or <c>-1</c> if the end of the
/// stream is reached.
/// </returns>
/// <exception cref="IOException">if an I/O error occurs</exception>
public virtual int Read()
{
return ReadByte();
}
/// <summary>
/// <para>
/// Reads some number of bytes from the input stream and stores them into
/// the buffer array <c>b</c>. 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.
/// </para>
/// <para>
/// If the length of <c>b</c> is zero, then no bytes are read and
/// <c>0</c> is returned; otherwise, there is an attempt to read at
/// least one byte. If no byte is available because the stream is at the
/// end of the file, the value <c>0</c> is returned; otherwise, at
/// least one byte is read and stored into <c>b</c>.
/// </para>
/// <para>
/// <p> The first byte read is stored into element <c>b[0]</c>, the
/// next one into <c>b[1]</c>, and so on. The number of bytes read is,
/// at most, equal to the length of <c>b</c>. Let <i>k</i> be the
/// number of bytes actually read; these bytes will be stored in elements
/// <c>b[0]</c> through <c>b[</c><i>k</i><c>-1]</c>,
/// leaving elements <c>b[</c><i>k</i><c>]</c> through
/// <c>b[b.length-1]</c> unaffected.</p>
/// </para>
/// <para>
/// <p> The <c>read(b)</c> method for class <c>InputStream</c>
/// has the same effect as: <pre><c> read(b, 0, b.length) </c></pre></p>
/// </para>
/// </summary>
/// <param name="b">the buffer into which the data is read.</param>
/// <returns>
/// the total number of bytes read into the buffer, or
/// <c>0</c> if there is no more data because the end of
/// the stream has been reached.
/// </returns>
/// <exception cref="IOException">If the first byte cannot be read for any reason
/// other than the end of the file, if the input stream has been closed, or
/// if some other I/O error occurs.</exception>
/// <exception cref="NullReferenceException">if <c>b</c> is <c>null</c>.</exception>
/// <see cref="Read(byte[], int, int)"/>
public virtual int Read(byte[] b)
{
return Read(b, 0, b.Length);
}
/// <summary>
/// <para>
/// Reads up to <c>len</c> bytes of data from the input stream into
/// an array of bytes. An attempt is made to read as many as
/// <c>len</c> bytes, but a smaller number may be read.
/// The number of bytes actually read is returned as an integer.
/// </para>
/// <para>
/// <p> This method blocks until input data is available, end of file is
/// detected, or an exception is thrown.</p>
/// </para>
/// <para>
/// <p> If <c>len</c> is zero, then no bytes are read and
/// <c>0</c> is returned; otherwise, there is an attempt to read at
/// least one byte. If no byte is available because the stream is at end of
/// file, the value <c>0</c> is returned; otherwise, at least one
/// byte is read and stored into <c>b</c>.</p>
/// </para>
/// <para>
/// <p> The first byte read is stored into element <c>b[off]</c>, the
/// next one into <c>b[off+1]</c>, and so on. The number of bytes read
/// is, at most, equal to <c>len</c>. Let <i>k</i> be the number of
/// bytes actually read; these bytes will be stored in elements
/// <c>b[off]</c> through <c>b[off+</c><i>k</i><c>-1]</c>,
/// leaving elements <c>b[off+</c><i>k</i><c>]</c> through
/// <c>b[off+len-1]</c> unaffected.</p>
/// </para>
/// <para>
/// <p> In every case, elements <c>b[0]</c> through
/// <c>b[off]</c> and elements <c>b[off+len]</c> through
/// <c>b[b.length-1]</c> are unaffected.</p>
/// </para>
/// <para>
/// <p> The <c>read(b,</c> <c>off,</c> <c>len)</c> method
/// for class <c>InputStream</c> simply calls the method
/// <c>read()</c> repeatedly. If the first such call results in an
/// <c>IOException</c>, that exception is returned from the call to
/// the <c>read(b,</c> <c>off,</c> <c>len)</c> method. If
/// any subsequent call to <c>read()</c> results in a
/// <c>IOException</c>, the exception is caught and treated as if it
/// were end of file; the bytes read up to that point are stored into
/// <c>b</c> and the number of bytes read before the exception
/// occurred is returned. The default implementation of this method blocks
/// until the requested amount of input data <c>len</c> has been read,
/// end of file is detected, or an exception is thrown. Subclasses are encouraged
/// to provide a more efficient implementation of this method.</p>
/// </para>
/// </summary>
/// <param name="b">the buffer into which the data is read.</param>
/// <param name="off">the start offset in array <c>b</c> at which the data is written.</param>
/// <param name="len">the maximum number of bytes to read.</param>
/// <returns>
/// the total number of bytes read into the buffer, or
/// <c>0</c> if there is no more data because the end of
/// the stream has been reached.</returns>
/// <exception cref="IOException">If the first byte cannot be read for any reason
/// other than end of file, or if the input stream has been closed, or if
/// some other I/O error occurs.</exception>
/// <exception cref="NullReferenceException">If <c>b</c> is <c>null</c>.</exception>
/// <exception cref="IndexOutOfRangeException">If <c>off</c> is negative,
/// <c>len</c> is negative, or <c>len</c> is greater than
/// <c>b.length - off</c></exception>
/// <see cref="Read()"/>
public override int Read(byte[] b, int off, int len)
{
if (b == null)
{
throw new ArgumentNullException();
}
else if (off < 0 || len < 0 || len > b.Length - off)
{
throw new IndexOutOfRangeException();
}
else if (len == 0)
{
return 0;
}
int c = Read();
if (c == -1)
{
return 0;
}
b[off] = (byte)c;
int i = 1;
try
{
for (; i < len; i++)
{
c = Read();
if (c == -1)
{
break;
}
b[off + i] = (byte)c;
}
}
catch (IOException)
{
}
return i;
}
/// <summary>
/// <para>
/// Skips over and discards <c>n</c> bytes of data from this input
/// stream. The <c>skip</c> method may, for a variety of reasons, end
/// up skipping over some smaller number of bytes, possibly <c>0</c>.
/// This may result from any of a number of conditions; reaching end of file
/// before <c>n</c> bytes have been skipped is only one possibility.
/// The actual number of bytes skipped is returned. If {@code n} is
/// negative, the {@code skip} method for class {@code InputStream} always
/// returns 0, and no bytes are skipped. Subclasses may handle the negative
/// value differently.
/// </para>
/// <para>
/// <p> The <c>skip</c> method of this class creates a
/// byte array and then repeatedly reads into it until <c>n</c> bytes
/// have been read or the end of the stream has been reached. Subclasses are
/// encouraged to provide a more efficient implementation of this method.
/// For instance, the implementation may depend on the ability to seek.</p>
/// </para>
/// </summary>
/// <param name="n">the number of bytes to be skipped.</param>
/// <returns>the actual number of bytes skipped.</returns>
/// <exception cref="IOException">if the stream does not support seek,
/// or if some other I/O error occurs.
/// </exception>
public virtual long Skip(long n)
{
long remaining = n;
int nr;
if (n <= 0)
{
return 0;
}
int size = (int)Math.Min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer = new byte[size];
while (remaining > 0)
{
nr = Read(skipBuffer, 0, (int)Math.Min(size, remaining));
if (nr < 0)
{
break;
}
remaining -= nr;
}
return n - remaining;
}
/// <summary>
/// <para>
/// Returns an estimate of the number of bytes that can be read (or
/// skipped over) from this input stream without blocking by the next
/// invocation of a method for this input stream. The next invocation
/// might be the same thread or another thread. A single read or skip of this
/// many bytes will not block, but may read or skip fewer bytes.
/// </para>
/// <para>
/// <p> Note that while some implementations of <see cref="InputStream"/> will return
/// the total number of bytes in the stream, many will not. It is
/// never correct to use the return value of this method to allocate
/// a buffer intended to hold all data in this stream.</p>
/// </para>
/// <para>
/// <p> A subclass' implementation of this method may choose to throw an
/// <see cref="IOException"/> if this input stream has been closed by
/// invoking the <see cref="Close"/> method.</p>
/// </para>
/// <para>
/// <p> The <see cref="Available"/> method for class <see cref="InputStream"/> always
/// returns {@code 0}.</p>
/// </para>
/// <para><p> This method should be overridden by subclasses.</p></para>
/// </summary>
/// <exception cref="IOException">if an I/O error occurs.</exception>
public virtual int Available()
{
return 0;
}
/// <summary>
/// <para>
/// Closes this input stream and releases any system resources associated
/// with the stream.
/// </para>
/// <para><p> The <c>Close</c> method of <c>InputStream</c> does nothing.</p></para>
/// </summary>
/// <exception cref="IOException">if an I/O error occurs.</exception>
public override void Close() { }
/// <summary>
/// <para>
/// Marks the current position in this input stream. A subsequent call to
/// the <c>reset</c> method repositions this stream at the last marked
/// position so that subsequent reads re-read the same bytes.
/// </para>
/// <para>
/// <p> The <c>readlimit</c> arguments tells this input stream to
/// allow that many bytes to be read before the mark position gets
/// invalidated.</p>
/// </para>
/// <para>
/// <p> The general contract of <c>mark</c> is that, if the method
/// <c>markSupported</c> returns <c>true</c>, the stream somehow
/// remembers all the bytes read after the call to <c>mark</c> and
/// stands ready to supply those same bytes again if and whenever the method
/// <c>reset</c> is called. However, the stream is not required to
/// remember any data at all if more than <c>readlimit</c> bytes are
/// read from the stream before <c>reset</c> is called.</p>
/// </para>
/// <para><p> Marking a closed stream should not have any effect on the stream.</p></para>
/// <para>
/// <p> The <c>mark</c> method of <c>InputStream</c> does
/// nothing.</p>
/// </para>
/// </summary>
/// <param name="readlimit">the maximum limit of bytes that can be read before
/// the mark position becomes invalid.
/// </param>
/// <see cref="Reset"/>
public virtual void Mark(int readlimit) { }
/// <summary>
/// <para>
/// Repositions this stream to the position at the time the
/// <c>mark</c> method was last called on this input stream.
/// </para>
/// <para><p> The general contract of <c>reset</c> is:</p></para>
/// <para>
/// <ul>
/// <li> If the method <c>markSupported</c> returns
/// <c>true</c>, then:
///
/// <ul><li> If the method <c>mark</c> has not been called since
/// the stream was created, or the number of bytes read from the stream
/// since <c>mark</c> was last called is larger than the argument
/// to <c>mark</c> at that last call, then an
/// <c>IOException</c> might be thrown.</li>
///
/// <li> If such an <c>IOException</c> is not thrown, then the
/// stream is reset to a state such that all the bytes read since the
/// most recent call to <c>mark</c> (or since the start of the
/// file, if <c>mark</c> has not been called) will be resupplied
/// to subsequent callers of the <c>read</c> method, followed by
/// any bytes that otherwise would have been the next input data as of
/// the time of the call to <c>reset</c>. </li>
///
/// <li> If the method <c>markSupported</c> returns
/// <c>false</c>, then:
///
/// <ul><li> The call to <c>reset</c> may throw an
/// <c>IOException</c>.</li>
///
/// <li> If an <c>IOException</c> is not thrown, then the stream
/// is reset to a fixed state that depends on the particular type of the
/// input stream and how it was created. The bytes that will be supplied
/// to subsequent callers of the <c>read</c> method depend on the
/// particular type of the input stream. </li></ul></li></ul></li></ul>
/// </para>
/// <para>
/// <p>The method <c>reset</c> for class <c>InputStream</c>
/// does nothing except throw an <c>IOException</c>.</p>
/// </para>
/// </summary>
public virtual void Reset()
{
throw new IOException("mark/reset not supported");
}
/// <summary>
/// Tests if this input stream supports the <c>mark</c> and
/// <c>reset</c> methods. Whether or not <c>mark</c> and
/// <c>reset</c> are supported is an invariant property of a
/// particular input stream instance. The <c>markSupported</c> method
/// of <c>InputStream</c> returns <c>false</c>.
/// </summary>
/// <returns>
/// <c>true</c> if this stream instance supports the mark
/// and reset methods; <c>false</c> otherwise.
/// <see cref="InputStream.Mark(int)"/>
/// <see cref="InputStream.Reset"/>
/// </returns>
public virtual bool MarkSupported()
{
return false;
}
public override bool CanWrite
{
get { return false; }
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}