Class FastBufferedInputStream

All Implemented Interfaces:
MeasurableStream, RepositionableStream, Closeable, AutoCloseable

public class FastBufferedInputStream extends MeasurableInputStream implements RepositionableStream
Lightweight, unsynchronized, aligned input stream buffering class with true skipping, measurability, repositionability and line reading support.

This class provides buffering for input streams, but it does so with purposes and an internal logic that are radically different from the ones adopted in BufferedInputStream. The main features follow.

  • There is no support for marking. All methods are unsychronized.

  • As an additional feature, this class implements the RepositionableStream and MeasurableStream interfaces. An instance of this class will try to cast the underlying byte stream to a RepositionableStream and to fetch by reflection the FileChannel underlying the given output stream, in this order. If either reference can be successfully fetched, you can use position(long) to reposition the stream. Much in the same way, an instance of this class will try to cast the the underlying byte stream to a MeasurableStream, and if this operation is successful, or if a FileChannel can be detected, then position() and length() will work as expected.

  • Due to erratic and unpredictable behaviour of InputStream.skip(long), which does not correspond to its specification and which Sun refuses to fix (see bug 6222822; don't be fooled by the “closed, fixed” label), this class peeks at the underlying stream and if it is System.in it uses repeated reads instead of calling InputStream.skip(long) on the underlying stream; moreover, skips and reads are tried alternately, so to guarantee that skipping less bytes than requested can be caused only by reaching the end of file.

  • This class keeps also track of the number of bytes read so far, so to be able to implement MeasurableStream.position() independently of underlying input stream.

  • This class has limited support for “reading a line” (whatever that means) from the underlying input stream. You can choose the set of line terminators that delimit lines.

Warning: Since fastutil 6.0.0, this class detects a implementations of MeasurableStream instead of subclasses MeasurableInputStream (which is deprecated).

Since:
4.4
  • Field Details

  • Constructor Details

    • FastBufferedInputStream

      public FastBufferedInputStream(InputStream is, byte[] buffer)
      Creates a new fast buffered input stream by wrapping a given input stream with a given buffer.
      Parameters:
      is - an input stream to wrap.
      buffer - a buffer of positive length.
    • FastBufferedInputStream

      public FastBufferedInputStream(InputStream is, int bufferSize)
      Creates a new fast buffered input stream by wrapping a given input stream with a given buffer size.
      Parameters:
      is - an input stream to wrap.
      bufferSize - the size in bytes of the internal buffer (greater than zero).
    • FastBufferedInputStream

      public FastBufferedInputStream(InputStream is)
      Creates a new fast buffered input stream by wrapping a given input stream with a buffer of DEFAULT_BUFFER_SIZE bytes.
      Parameters:
      is - an input stream to wrap.
  • Method Details

    • read

      public int read() throws IOException
      Specified by:
      read in class InputStream
      Throws:
      IOException
    • read

      public int read(byte[] b, int offset, int length) throws IOException
      Overrides:
      read in class InputStream
      Throws:
      IOException
    • readLine

      public int readLine(byte[] array) throws IOException
      Reads a line into the given byte array using all terminators.
      Parameters:
      array - byte array where the next line will be stored.
      Returns:
      the number of bytes actually placed in array, or -1 at end of file.
      Throws:
      IOException
      See Also:
    • readLine

      public int readLine(byte[] array, EnumSet<FastBufferedInputStream.LineTerminator> terminators) throws IOException
      Reads a line into the given byte array.
      Parameters:
      array - byte array where the next line will be stored.
      terminators - a set containing the line termination sequences that we want to consider as valid.
      Returns:
      the number of bytes actually placed in array, or -1 at end of file.
      Throws:
      IOException
      See Also:
    • readLine

      public int readLine(byte[] array, int off, int len) throws IOException
      Reads a line into the given byte-array fragment using all terminators.
      Parameters:
      array - byte array where the next line will be stored.
      off - the first byte to use in array.
      len - the maximum number of bytes to read.
      Returns:
      the number of bytes actually placed in array, or -1 at end of file.
      Throws:
      IOException
      See Also:
    • readLine

      public int readLine(byte[] array, int off, int len, EnumSet<FastBufferedInputStream.LineTerminator> terminators) throws IOException
      Reads a line into the given byte-array fragment.

      Reading lines (i.e., characters) out of a byte stream is not always sensible (methods available to that purpose in old versions of Java have been mercilessly deprecated). Nonetheless, in several situations, such as when decoding network protocols or headers known to be ASCII, it is very useful to be able to read a line from a byte stream.

      This method will attempt to read the next line into array starting at off, reading at most len bytes. The read, however, will be stopped by the end of file or when meeting a line terminator. Of course, for this operation to be sensible the encoding of the text contained in the stream, if any, must not generate spurious carriage returns or line feeds. Note that the termination detection uses a maximisation criterion, so if you specify both FastBufferedInputStream.LineTerminator.CR and FastBufferedInputStream.LineTerminator.CR_LF meeting a pair CR/LF will consider the whole pair a terminator.

      Terminators are not copied into array or included in the returned count. The returned integer can be used to check whether the line is complete: if it is smaller than len, then more bytes might be available, but note that this method (contrarily to read(byte[], int, int)) can legitimately return zero when len is nonzero just because a terminator was found as the first character. Thus, the intended usage of this method is to call it on a given array, check whether len bytes have been read, and if so try again (possibly extending the array) until a number of read bytes strictly smaller than len (possibly, -1) is returned.

      If you need to guarantee that a full line is read, use the following idiom:

       int start = off, len;
       while((len = fbis.readLine(array, start, array.length - start, terminators)) == array.length - start) {
           start += len;
           array = ByteArrays.grow(array, array.length + 1);
       }
       

      At the end of the loop, the line will be placed in array starting at off (inclusive) and ending at start + Math.max(len, 0) (exclusive).

      Parameters:
      array - byte array where the next line will be stored.
      off - the first byte to use in array.
      len - the maximum number of bytes to read.
      terminators - a set containing the line termination sequences that we want to consider as valid.
      Returns:
      the number of bytes actually placed in array, or -1 at end of file. Note that the returned number will be len if no line termination sequence specified in terminators has been met before scanning len byte, and if also we did not meet the end of file.
      Throws:
      IOException
    • position

      public void position(long newPosition) throws IOException
      Description copied from interface: RepositionableStream
      Sets the current stream position.
      Specified by:
      position in interface RepositionableStream
      Parameters:
      newPosition - the new stream position.
      Throws:
      IOException
    • position

      public long position() throws IOException
      Description copied from interface: RepositionableStream
      Returns the current stream position.
      Specified by:
      position in interface MeasurableStream
      Specified by:
      position in interface RepositionableStream
      Returns:
      the current stream position.
      Throws:
      IOException
    • length

      public long length() throws IOException
      Returns the length of the underlying input stream, if it is measurable.
      Specified by:
      length in interface MeasurableStream
      Returns:
      the length of the underlying input stream.
      Throws:
      UnsupportedOperationException - if the underlying input stream is not measurable and cannot provide a FileChannel.
      IOException
    • skip

      public long skip(long n) throws IOException
      Skips over and discards the given number of bytes of data from this fast buffered input stream.

      As explained in the class documentation, the semantics of InputStream.skip(long) is fatally flawed. This method provides additional semantics as follows: it will skip the provided number of bytes, unless the end of file has been reached.

      Additionally, if the underlying input stream is System.in this method will use repeated reads instead of invoking InputStream.skip(long).

      Overrides:
      skip in class InputStream
      Parameters:
      n - the number of bytes to skip.
      Returns:
      the number of bytes actually skipped; it can be smaller than n only if the end of file has been reached.
      Throws:
      IOException
      See Also:
    • available

      public int available() throws IOException
      Overrides:
      available in class InputStream
      Throws:
      IOException
    • close

      public void close() throws IOException
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Overrides:
      close in class InputStream
      Throws:
      IOException
    • flush

      public void flush()
      Resets the internal logic of this fast buffered input stream, clearing the buffer.

      All buffering information is discarded, and the number of bytes read so far (and thus, also the current position) is adjusted to reflect this fact.

      This method is mainly useful for re-reading files that have been overwritten externally.

    • reset

      @Deprecated public void reset()
      Deprecated.
      As of fastutil 5.0.4, replaced by flush(). The old semantics of this method does not contradict InputStream's contract, as the semantics of reset() is undefined if InputStream.markSupported() returns false. On the other hand, the name was really a poor choice.
      Resets the internal logic of this fast buffered input stream.
      Overrides:
      reset in class InputStream