public class FastBufferedInputStream extends MeasurableInputStream implements RepositionableStream
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).
Modifier and Type | Class and Description |
---|---|
static class |
FastBufferedInputStream.LineTerminator
An enumeration of the supported line terminators.
|
Modifier and Type | Field and Description |
---|---|
static EnumSet<FastBufferedInputStream.LineTerminator> |
ALL_TERMINATORS
A set containing all available line terminators.
|
static int |
DEFAULT_BUFFER_SIZE
The default size of the internal buffer in bytes (8Ki).
|
Constructor and Description |
---|
FastBufferedInputStream(InputStream is)
Creates a new fast buffered input stream by wrapping a given input stream with a buffer of
DEFAULT_BUFFER_SIZE bytes. |
FastBufferedInputStream(InputStream is,
byte[] buffer)
Creates a new fast buffered input stream by wrapping a given input stream with a given buffer.
|
FastBufferedInputStream(InputStream is,
int bufferSize)
Creates a new fast buffered input stream by wrapping a given input stream with a given buffer size.
|
Modifier and Type | Method and Description |
---|---|
int |
available() |
void |
close() |
void |
flush()
Resets the internal logic of this fast buffered input stream, clearing the buffer.
|
long |
length()
Returns the length of the underlying input stream, if it is measurable.
|
long |
position()
Returns the current stream position.
|
void |
position(long newPosition)
Sets the current stream position.
|
int |
read() |
int |
read(byte[] b,
int offset,
int length) |
int |
readLine(byte[] array)
Reads a line into the given byte array using all terminators.
|
int |
readLine(byte[] array,
EnumSet<FastBufferedInputStream.LineTerminator> terminators)
Reads a line into the given byte array.
|
int |
readLine(byte[] array,
int off,
int len)
Reads a line into the given byte-array fragment using all terminators.
|
int |
readLine(byte[] array,
int off,
int len,
EnumSet<FastBufferedInputStream.LineTerminator> terminators)
Reads a line into the given byte-array fragment.
|
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. |
long |
skip(long n)
Skips over and discards the given number of bytes of data from this fast buffered input stream.
|
mark, markSupported, read
public static final int DEFAULT_BUFFER_SIZE
public static final EnumSet<FastBufferedInputStream.LineTerminator> ALL_TERMINATORS
public FastBufferedInputStream(InputStream is, byte[] buffer)
is
- an input stream to wrap.buffer
- a buffer of positive length.public FastBufferedInputStream(InputStream is, int bufferSize)
is
- an input stream to wrap.bufferSize
- the size in bytes of the internal buffer (greater than zero).public FastBufferedInputStream(InputStream is)
DEFAULT_BUFFER_SIZE
bytes.is
- an input stream to wrap.public int read() throws IOException
read
in class InputStream
IOException
public int read(byte[] b, int offset, int length) throws IOException
read
in class InputStream
IOException
public int readLine(byte[] array) throws IOException
array
- byte array where the next line will be stored.array
, or -1 at end of file.IOException
readLine(byte[], int, int, EnumSet)
public int readLine(byte[] array, EnumSet<FastBufferedInputStream.LineTerminator> terminators) throws IOException
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.array
, or -1 at end of file.IOException
readLine(byte[], int, int, EnumSet)
public int readLine(byte[] array, int off, int len) throws IOException
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.array
, or -1 at end of file.IOException
readLine(byte[], int, int, EnumSet)
public int readLine(byte[] array, int off, int len, EnumSet<FastBufferedInputStream.LineTerminator> terminators) throws IOException
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).
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.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.IOException
public void position(long newPosition) throws IOException
RepositionableStream
position
in interface RepositionableStream
newPosition
- the new stream position.IOException
public long position() throws IOException
RepositionableStream
position
in interface MeasurableStream
position
in interface RepositionableStream
IOException
public long length() throws IOException
length
in interface MeasurableStream
UnsupportedOperationException
- if the underlying input stream is not measurable and
cannot provide a FileChannel
.IOException
public long skip(long n) throws IOException
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)
.
skip
in class InputStream
n
- the number of bytes to skip.n
only if the end of file has been reached.IOException
InputStream.skip(long)
public int available() throws IOException
available
in class InputStream
IOException
public void close() throws IOException
close
in interface Closeable
close
in interface AutoCloseable
close
in class InputStream
IOException
public void flush()
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.
@Deprecated public void reset()
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.reset
in class InputStream