Class ProcessingBufferedReader
- java.lang.Object
-
- java.io.Reader
-
- com.globalmentor.io.ProcessingBufferedReader
-
- All Implemented Interfaces:
java.io.Closeable
,java.lang.AutoCloseable
,java.lang.Readable
- Direct Known Subclasses:
ParseReader
public class ProcessingBufferedReader extends java.io.Reader
A reader that buffers data and allows this data to be processed before handing it to the consumer. This class also allows marking and resetting, as well as peeking upcoming buffered characters.The class maintains an internal buffer, which is of size bufferSize, part of which is used for the undo buffer of size undoBufferSize. The following indexes are maintained in the buffer:
- readIndex
- The index of the next character to be read.
- peekIndex
- The index of the next character to be peeked. After each read this is set to equal readIndex.
- bufferEndIndex
- The index directly after the last character in the buffer.
- fetchBufferIndex
- The index where a new buffer should be read. The default implementation is for fetchBufferIndex to equal bufferEndIndex, but processing of a stream may determine that rebuffering should occur earlier -- if a "\r\n" is split across buffers, for instance.
- Author:
- Garret Wilson
- See Also:
Reader
-
-
Field Summary
Fields Modifier and Type Field Description static int
DEFAULT_BUFFER_SIZE
The default size of buffered data.static int
DEFAULT_UNDO_BUFFER_SIZE
The default size of the buffer for unreading data.static int
END_VALUE
The value which indicates the end of the data has been reached.
-
Constructor Summary
Constructors Constructor Description ProcessingBufferedReader(java.io.Reader reader)
Constructor to create aProcessingBufferedReader
from another reader.ProcessingBufferedReader(java.io.Reader reader, java.lang.CharSequence prereadCharacters)
Constructor to create aProcessingBufferedReader
from another reader, along with several characters that have already been read.ProcessingBufferedReader(java.lang.CharSequence characters)
Constructor to create a reader from the contents of a character sequence.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description protected void
adjustIndexes(int moveDelta)
Adjusts all indexes by a certain amount.void
close()
Close the stream.protected void
createBuffer()
Creates a new buffer and initializes buffer indexes.protected int
fetchBuffer()
Fills a buffer with new information.protected char[]
getBuffer()
protected int
getBufferEndIndex()
int
getBufferSize()
protected int
getFetchBufferIndex()
protected int
getMarkIndex()
protected int
getPeekIndex()
protected java.io.Reader
getReader()
protected int
getReadIndex()
int
getUndoBufferSize()
protected void
initializeIndexes()
Initializes relevant buffer indexes when, for example, the buffer is first created.boolean
isEnd()
protected boolean
isLastBuffer()
protected void
loadBuffer(java.lang.CharSequence bufferCharacters)
Loads the buffer with the specified characters.void
mark(int readAheadLimit)
boolean
markSupported()
protected void
moveBuffer(int sourceIndex, int destIndex, int len)
Moves a portion of the buffer.int
peek()
Peeks at the next character to be read.int
peek(char[] cbuf, int off, int len)
Peeks a specified number of characters into a portion of an array.protected void
processBufferedData(int newDataBeginIndex)
Provides away to do initial processing on newly-buffered data.int
read()
Read a single character.int
read(char[] cbuf, int off, int len)
Read characters into a portion of an array.boolean
ready()
void
reset()
void
resetPeek()
Resets any characters we've peeked so that the next peek will reflect the next character which will be read.protected void
setBufferEndIndex(int bufferEndIndex)
Sets the index directly after the end of the last character in the buffer.protected void
setEnd(boolean isEnd)
Sets whether the end of the data has been reached.protected void
setFetchBufferIndex(int fetchBufferIndex)
Sets the index where a new buffer should be read.protected void
setLastBuffer(boolean lastBuffer)
Sets whether or not the previously-read buffer was the last.protected void
setPeekIndex(int peekIndex)
Sets the index of the next character to be peeked.protected void
setReadIndex(int readIndex)
Sets the index of the next character to be read and checks to see if the end of the file has been reached.long
skip(long n)
Skips the specified number of characters.void
unread(char[] cbuf)
Pushes back an array of characters.void
unread(char[] cbuf, int off, int len)
Pushes back a portion of an array of characters.void
unread(int c)
Pushes back a single character.void
unskip(int n)
Reverses the reading position to the previous characters read.protected boolean
updateEnd()
Checks to see if the end of the data has been reached, and updates the EOF property if so.
-
-
-
Field Detail
-
END_VALUE
public static final int END_VALUE
The value which indicates the end of the data has been reached.- See Also:
read()
, Constant Field Values
-
DEFAULT_UNDO_BUFFER_SIZE
public static final int DEFAULT_UNDO_BUFFER_SIZE
The default size of the buffer for unreading data.- See Also:
- Constant Field Values
-
DEFAULT_BUFFER_SIZE
public static final int DEFAULT_BUFFER_SIZE
The default size of buffered data.- See Also:
- Constant Field Values
-
-
Constructor Detail
-
ProcessingBufferedReader
public ProcessingBufferedReader(java.io.Reader reader)
Constructor to create aProcessingBufferedReader
from another reader.- Parameters:
reader
- The reader that contains the data.
-
ProcessingBufferedReader
public ProcessingBufferedReader(java.io.Reader reader, java.lang.CharSequence prereadCharacters) throws java.io.IOException
Constructor to create aProcessingBufferedReader
from another reader, along with several characters that have already been read. prereadCharacters must be less than or equal to the length of the buffer.- Parameters:
reader
- The reader that contains the data.prereadCharacters
- The characters that have already been read.- Throws:
java.io.IOException
- if prereadCharacters is too long for the buffer.
-
ProcessingBufferedReader
public ProcessingBufferedReader(java.lang.CharSequence characters) throws java.io.IOException
Constructor to create a reader from the contents of a character sequence.- Parameters:
characters
- The string that should be used for input.- Throws:
java.io.IOException
- if an I/O error occurs.
-
-
Method Detail
-
getBufferSize
public int getBufferSize()
- Returns:
- The size of buffered data, including undo buffer space.
- See Also:
getUndoBufferSize()
-
getUndoBufferSize
public int getUndoBufferSize()
- Returns:
- The size of the extra buffer for unreading data.
-
getBuffer
protected char[] getBuffer()
- Returns:
- The internal buffer used to hold characters.
-
isLastBuffer
protected boolean isLastBuffer()
- Returns:
- Whether or not we've read the last buffer. Technically the last buffer could have been read, but it might have been filled completely, in which
case this function would still return
false
.
-
setLastBuffer
protected void setLastBuffer(boolean lastBuffer)
Sets whether or not the previously-read buffer was the last.- Parameters:
lastBuffer
- Whether the last buffer has been read.
-
getReadIndex
protected int getReadIndex()
- Returns:
- The index of the next character to be read.
-
setReadIndex
protected void setReadIndex(int readIndex) throws java.io.IOException
Sets the index of the next character to be read and checks to see if the end of the file has been reached. Resets peeking.- Parameters:
readIndex
- The index of the next character to be read.- Throws:
java.io.IOException
- if an I/O error occurs.- See Also:
updateEnd()
-
getPeekIndex
protected int getPeekIndex()
- Returns:
- The index of the next character to be peeked. After each read this is set to equal ReadIndex.
-
setPeekIndex
protected void setPeekIndex(int peekIndex)
Sets the index of the next character to be peeked.- Parameters:
peekIndex
- The index of the next character to be peeked.
-
getBufferEndIndex
protected int getBufferEndIndex()
- Returns:
- The index directly after the end of the last character in the buffer.
-
setBufferEndIndex
protected void setBufferEndIndex(int bufferEndIndex)
Sets the index directly after the end of the last character in the buffer.- Parameters:
bufferEndIndex
- The index directly after the end of the last character in the buffer.
-
getFetchBufferIndex
protected int getFetchBufferIndex()
- Returns:
- The index where a new buffer should be read. Usually equals
BufferEndIndex
. - See Also:
getBufferEndIndex()
-
setFetchBufferIndex
protected void setFetchBufferIndex(int fetchBufferIndex)
Sets the index where a new buffer should be read.- Parameters:
fetchBufferIndex
- The index where a new buffer should be read.- See Also:
setBufferEndIndex(int)
-
isEnd
public boolean isEnd()
- Returns:
- Whether or not the end of the data has been reached.
-
setEnd
protected void setEnd(boolean isEnd)
Sets whether the end of the data has been reached.- Parameters:
isEnd
- Whether the end of the data has been reached.
-
ready
public boolean ready() throws java.io.IOException
This implementation returns true if there are characters already in the buffer that would be used without fetching another buffer, or if the underlying reader is ready.
- Overrides:
ready
in classjava.io.Reader
- Throws:
java.io.IOException
-
markSupported
public boolean markSupported()
- Overrides:
markSupported
in classjava.io.Reader
-
getMarkIndex
protected int getMarkIndex()
- Returns:
- The index in the buffer of the mark, which will be negative if the reader is not marked.
-
mark
public void mark(int readAheadLimit) throws java.io.IOException
- Overrides:
mark
in classjava.io.Reader
- Throws:
java.lang.IllegalArgumentException
- if the given read-ahead limit is greater thangetUndoBufferSize()
.java.io.IOException
- See Also:
getUndoBufferSize()
-
reset
public void reset() throws java.io.IOException
This implementation resets peeking.
This implementation does not support resetting without first marking.
- Overrides:
reset
in classjava.io.Reader
- Throws:
java.io.IOException
- if the reader is not currently marked.- See Also:
resetPeek()
-
getReader
protected java.io.Reader getReader()
- Returns:
- The reader from which we extract the information.
-
createBuffer
protected void createBuffer()
Creates a new buffer and initializes buffer indexes. Any data in previous buffers will be erased.
-
loadBuffer
protected void loadBuffer(java.lang.CharSequence bufferCharacters) throws java.io.IOException
Loads the buffer with the specified characters. bufferCharacters must be less than or equal to the room left in the buffer.- Parameters:
bufferCharacters
- The characters which should be placed in the buffer.- Throws:
java.io.IOException
- if bufferCharacters is too long for the buffer.
-
initializeIndexes
protected void initializeIndexes()
Initializes relevant buffer indexes when, for example, the buffer is first created. This implementation sets the read index and the peek index; the other buffer end and fetch buffer indexes will be set by methods that set the buffer itself, such ascreateBuffer()
. This method is called from withinsetBuffer(char[])
.- See Also:
createBuffer()
,setBuffer(char[])
-
adjustIndexes
protected void adjustIndexes(int moveDelta)
Adjusts all indexes by a certain amount. This method is currently called byfetchBuffer()
after moving data in the buffer.The mark index is adjusted as well. If adjusting the indexes moves the mark index below the bottom of the buffer, the reader has effectively become unmarked.
- Parameters:
moveDelta
- The number of characters to move the indexes, positive for forwards, negative for backwards.- See Also:
fetchBuffer()
-
moveBuffer
protected void moveBuffer(int sourceIndex, int destIndex, int len)
Moves a portion of the buffer. This method is called fromfetchBuffer()
before fetching data.- Parameters:
sourceIndex
- The index in the buffer to be moved.destIndex
- The destination in the buffer for the data being moved.len
- The number of characters to move.- See Also:
fetchBuffer()
-
fetchBuffer
protected int fetchBuffer() throws java.io.IOException
Fills a buffer with new information.This method will read as much data as it can without blocking, and return the number of characters read.
If the current buffer is full, the last section of the buffer will be moved to the front to make room for more data; otherwise, the data will simply be appended to the buffer.
This method does not change the EOF status.
- Returns:
- The number of characters fetched, or -1 if the end of the file was reached.
- Throws:
java.io.IOException
- if an I/O error occurs.- See Also:
isLastBuffer()
-
processBufferedData
protected void processBufferedData(int newDataBeginIndex) throws java.io.IOException
Provides away to do initial processing on newly-buffered data. The fetch index may be modified.- Parameters:
newDataBeginIndex
- The starting index of the newly fetched data.- Throws:
java.io.IOException
- if an I/O error occurs.- See Also:
getFetchBufferIndex()
-
updateEnd
protected boolean updateEnd() throws java.io.IOException
Checks to see if the end of the data has been reached, and updates the EOF property if so. If the EOF property is already set totrue
, this function does nothing.- Returns:
- Whether or not the end of the file has been reached.
- Throws:
java.io.IOException
- if an I/O error occurs.- See Also:
isEnd()
-
read
public int read() throws java.io.IOException
Read a single character. This method will block until a character is available, an I/O error occurs, or the end of the stream is reached.- Overrides:
read
in classjava.io.Reader
- Returns:
- The character read, as an integer in the range 0 to 16383 (0x00-0xffff), or -1 if the end of the stream has been reached.
- Throws:
java.io.IOException
- if an I/O error occurs.
-
read
public int read(char[] cbuf, int off, int len) throws java.io.IOException
Read characters into a portion of an array. This method will block until some input is available, an I/O error occurs, or the end of the stream is reached. Resets peeking.- Specified by:
read
in classjava.io.Reader
- Parameters:
cbuf
- Destination buffer.off
- Offset at which to start storing characters.len
- Maximum number of characters to read.- Returns:
- The number of characters read, or -1 if the end of the stream has been reached.
- Throws:
java.io.IOException
- if an I/O error occurs.
-
unread
public void unread(int c) throws java.io.IOException
Pushes back a single character. Resets peeking.- Parameters:
c
- The character to push back.- Throws:
java.io.IOException
- if there is no room to push back characters (the undo buffer is full) or some other I/O error occurs.
-
unread
public void unread(char[] cbuf, int off, int len) throws java.io.IOException
Pushes back a portion of an array of characters. Resets peeking.- Parameters:
cbuf
- The array of characters to push back.off
- The offset of the first character to push back.len
- The number of characters to push back.- Throws:
java.io.IOException
- if there is no room to push back characters (the undo buffer is full) or some other I/O error occurs.
-
unread
public void unread(char[] cbuf) throws java.io.IOException
Pushes back an array of characters. Resets peeking.- Parameters:
cbuf
- The array of characters to push back.- Throws:
java.io.IOException
- if there is no room to push back characters (the undo buffer is full) or some other I/O error occurs.
-
close
public void close() throws java.io.IOException
Close the stream. Once a stream has been closed, further read(), ready(), mark(), or reset() invocations will throw an IOException.Closing a previously-closed stream, however, has no effect.
- Specified by:
close
in interfacejava.lang.AutoCloseable
- Specified by:
close
in interfacejava.io.Closeable
- Specified by:
close
in classjava.io.Reader
- Throws:
java.io.IOException
- if an I/O error occurs.
-
peek
public int peek() throws java.io.IOException
Peeks at the next character to be read. Each successive peek will return a successive character.This function is reset with every call to #read().
Since every peek reads a successive character,
resetPeek()
should be called if it must be ensured that the next character peeked is the next character to be read.- Returns:
- The next character that will be read after the character retrieved in the last
read()
orpeek()
, or -1 if there are no characters left to read. - Throws:
java.io.IOException
- if an I/O error occurs.- See Also:
read()
,resetPeek()
-
peek
public int peek(char[] cbuf, int off, int len) throws java.io.IOException
Peeks a specified number of characters into a portion of an array. This method will block until some input is available, an I/O error occurs, or the end of the stream is reached.Resets peeking.
- Parameters:
cbuf
- Destination buffer.off
- Offset at which to start storing characters.len
- Maximum number of characters to peek.- Returns:
- The number of characters peeked, or 0 if the end of the stream has been reached.
- Throws:
java.io.IOException
- if an I/O error occurs.
-
resetPeek
public void resetPeek()
Resets any characters we've peeked so that the next peek will reflect the next character which will be read.Does not affect the next character to be read.
-
skip
public long skip(long n) throws java.io.IOException
Skips the specified number of characters. This method will block until some characters are available, an I/O error occurs, or the end of the stream is reached.Resets peeking.
- Overrides:
skip
in classjava.io.Reader
- Parameters:
n
- The number of characters to skip.- Returns:
- The number of characters actually skipped.
- Throws:
java.io.IOException
- if an I/O error occurs.
-
unskip
public void unskip(int n) throws java.io.IOException
Reverses the reading position to the previous characters read. Functions similar to unread() except that the unread characters will always be the characters that were previously read.Resets peeking.
- Parameters:
n
- The number of characters to unskip.- Throws:
java.io.IOException
- if there is no room to push back characters (the undo buffer is full) or some other I/O error occurs.- See Also:
unread(char[])
-
-