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
    • Constructor Detail

      • 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 Detail

      • 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(byte[], int, int, EnumSet)
      • 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
      • 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:
        InputStream.skip(long)
      • 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