📄 circularcharbuffer.java
字号:
/** * Tell whether this stream supports the mark() operation. * * @return true, mark is supported. */ public boolean markSupported() { return true; } /** * 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. * * @return The character read, as an integer in the range 0 to 65535 (0x00-0xffff), * or -1 if the end of the stream has been reached * @throws IOException if the stream is closed. */ public int read() throws IOException { while (true){ synchronized (CircularCharBuffer.this){ if (readerClosed) throw new IOException("Reader has been closed; cannot read from a closed Reader."); int available = available(); if (available > 0){ int result = buffer[readPosition] & 0xffff; readPosition++; if (readPosition == buffer.length){ readPosition = 0; } ensureMark(); return result; } else if (writerClosed){ return -1; } } try { Thread.sleep(100); } catch(Exception x){ throw new IOException("Blocking read operation interrupted."); } } } /** * Read characters into an array. * This method will block until some input is available, * an I/O error occurs, or the end of the stream is reached. * * @param cbuf Destination buffer. * @return The number of characters read, or -1 if the end of * the stream has been reached * @throws IOException if the stream is closed. */ public int read(char[] cbuf) throws IOException { return read(cbuf, 0, cbuf.length); } /** * 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. * * @param cbuf Destination buffer. * @param off Offset at which to start storing characters. * @param len Maximum number of characters to read. * @return The number of characters read, or -1 if the end of * the stream has been reached * @throws IOException if the stream is closed. */ public int read(char[] cbuf, int off, int len) throws IOException { while (true){ synchronized (CircularCharBuffer.this){ if (readerClosed) throw new IOException("Reader has been closed; cannot read from a closed Reader."); int available = available(); if (available > 0){ int length = Math.min(len, available); int firstLen = Math.min(length, buffer.length - readPosition); int secondLen = length - firstLen; System.arraycopy(buffer, readPosition, cbuf, off, firstLen); if (secondLen > 0){ System.arraycopy(buffer, 0, cbuf, off+firstLen, secondLen); readPosition = secondLen; } else { readPosition += length; } if (readPosition == buffer.length) { readPosition = 0; } ensureMark(); return length; } else if (writerClosed){ return -1; } } try { Thread.sleep(100); } catch(Exception x){ throw new IOException("Blocking read operation interrupted."); } } } /** * Tell whether this stream is ready to be read. * * @return True if the next read() is guaranteed not to block for input, * false otherwise. Note that returning false does not guarantee that * the next read will block. * @throws IOException if the stream is closed. */ public boolean ready() throws IOException { synchronized (CircularCharBuffer.this){ if (readerClosed) throw new IOException("Reader has been closed, it is not ready."); return (available() > 0); } } /** * Reset the stream. * If the stream has been marked, then attempt to reposition i * at the mark. If the stream has not been marked, or more characters * than the readAheadLimit have been read, this method has no effect. * * @throws IOException if the stream is closed. */ public void reset() throws IOException { synchronized (CircularCharBuffer.this){ if (readerClosed) throw new IOException("Reader has been closed; cannot reset a closed Reader."); readPosition = markPosition; } } /** * Skip characters. * This method will block until some characters are available, * an I/O error occurs, or the end of the stream is reached. * * @param n The number of characters to skip * @return The number of characters actually skipped * @throws IllegalArgumentException if n is negative. * @throws IOException if the stream is closed. */ public long skip(long n) throws IOException, IllegalArgumentException { while (true){ synchronized (CircularCharBuffer.this){ if (readerClosed) throw new IOException("Reader has been closed; cannot skip characters on a closed Reader."); int available = available(); if (available > 0){ int length = Math.min((int)n, available); int firstLen = Math.min(length, buffer.length - readPosition); int secondLen = length - firstLen; if (secondLen > 0){ readPosition = secondLen; } else { readPosition += length; } if (readPosition == buffer.length) { readPosition = 0; } return length; } else if (writerClosed){ return 0; } } try { Thread.sleep(100); } catch(Exception x){ throw new IOException("Blocking read operation interrupted."); } } } } /** * Class for writing to a circular character buffer. * If the buffer is full, the writes will either block * until there is some space available or throw an IOException * based on the CircularCharBuffer's preference. */ protected class CircularCharBufferWriter extends Writer { /** * Close the stream, flushing it first. * This will cause the reader associated with this circular buffer * to read its last characters once it empties the buffer. * Once a stream has been closed, further write() or flush() invocations * will cause an IOException to be thrown. Closing a previously-closed stream, * however, has no effect. * * @throws IOException never. */ public void close() throws IOException { synchronized (CircularCharBuffer.this){ if (!writerClosed){ flush(); } writerClosed = true; } } /** * Flush the stream. * * @throws IOException if the stream is closed. */ public void flush() throws IOException { if (writerClosed) throw new IOException("Writer has been closed; cannot flush a closed Writer."); if (readerClosed) throw new IOException("Buffer closed by Reader; cannot flush."); // this method needs to do nothing } /** * Write an array of characters. * If the buffer allows blocking writes, this method will block until * all the data has been written rather than throw an IOException. * * @param cbuf Array of characters to be written * @throws BufferOverflowException if buffer does not allow blocking writes * and the buffer is full. If the exception is thrown, no data * will have been written since the buffer was set to be non-blocking. * @throws IOException if the stream is closed, or the write is interrupted. */ public void write(char[] cbuf) throws IOException { write(cbuf, 0, cbuf.length); } /** * Write a portion of an array of characters. * If the buffer allows blocking writes, this method will block until * all the data has been written rather than throw an IOException. * * @param cbuf Array of characters * @param off Offset from which to start writing characters * @param len - Number of characters to write * @throws BufferOverflowException if buffer does not allow blocking writes * and the buffer is full. If the exception is thrown, no data * will have been written since the buffer was set to be non-blocking. * @throws IOException if the stream is closed, or the write is interrupted. */ public void write(char[] cbuf, int off, int len) throws IOException { while (len > 0){ synchronized (CircularCharBuffer.this){ if (writerClosed) throw new IOException("Writer has been closed; cannot write to a closed Writer."); if (readerClosed) throw new IOException("Buffer closed by Reader; cannot write to a closed buffer."); int spaceLeft = spaceLeft(); while (infinite && spaceLeft < len){ resize(); spaceLeft = spaceLeft(); } if (!blockingWrite && spaceLeft < len) throw new BufferOverflowException("CircularCharBuffer is full; cannot write " + len + " characters"); int realLen = Math.min(len, spaceLeft); int firstLen = Math.min(realLen, buffer.length - writePosition); int secondLen = Math.min(realLen - firstLen, buffer.length - markPosition - 1); int written = firstLen + secondLen; if (firstLen > 0){ System.arraycopy(cbuf, off, buffer, writePosition, firstLen); } if (secondLen > 0){ System.arraycopy(cbuf, off+firstLen, buffer, 0, secondLen); writePosition = secondLen; } else { writePosition += written; } if (writePosition == buffer.length) { writePosition = 0; } off += written; len -= written; } if (len > 0){ try { Thread.sleep(100); } catch(Exception x){ throw new IOException("Waiting for available space in buffer interrupted."); } } } } /** * Write a single character. * The character to be written is contained in the 16 low-order bits of the * given integer value; the 16 high-order bits are ignored. * If the buffer allows blocking writes, this method will block until * all the data has been written rather than throw an IOException. * * @param c int specifying a character to be written. * @throws BufferOverflowException if buffer does not allow blocking writes * and the buffer is full. * @throws IOException if the stream is closed, or the write is interrupted. */ public void write(int c) throws IOException { boolean written = false; while (!written){ synchronized (CircularCharBuffer.this){ if (writerClosed) throw new IOException("Writer has been closed; cannot write to a closed Writer."); if (readerClosed) throw new IOException("Buffer closed by Reader; cannot write to a closed buffer."); int spaceLeft = spaceLeft(); while (infinite && spaceLeft < 1){ resize(); spaceLeft = spaceLeft(); } if (!blockingWrite && spaceLeft < 1) throw new BufferOverflowException("CircularCharBuffer is full; cannot write 1 character"); if (spaceLeft > 0){ buffer[writePosition] = (char)(c & 0xffff); writePosition++; if (writePosition == buffer.length) { writePosition = 0; } written = true; } } if (!written){ try { Thread.sleep(100); } catch(Exception x){ throw new IOException("Waiting for available space in buffer interrupted."); } } } } /** * Write a string. * If the buffer allows blocking writes, this method will block until * all the data has been written rather than throw an IOException. * * @param str String to be written * @throws BufferOverflowException if buffer does not allow blocking writes * and the buffer is full. If the exception is thrown, no data * will have been written since the buffer was set to be non-blocking. * @throws IOException if the stream is closed, or the write is interrupted. */ public void write(String str) throws IOException { write(str, 0, str.length()); } /** * Write a portion of a string. * If the buffer allows blocking writes, this method will block until * all the data has been written rather than throw an IOException. * * @param str A String * @param off Offset from which to start writing characters * @param len Number of characters to write * @throws BufferOverflowException if buffer does not allow blocking writes * and the buffer is full. If the exception is thrown, no data * will have been written since the buffer was set to be non-blocking. * @throws IOException if the stream is closed, or the write is interrupted. */ public void write(String str, int off, int len) throws IOException { while (len > 0){ synchronized (CircularCharBuffer.this){ if (writerClosed) throw new IOException("Writer has been closed; cannot write to a closed Writer."); if (readerClosed) throw new IOException("Buffer closed by Reader; cannot write to a closed buffer."); int spaceLeft = spaceLeft(); while (infinite && spaceLeft < len){ resize(); spaceLeft = spaceLeft(); } if (!blockingWrite && spaceLeft < len) throw new BufferOverflowException("CircularCharBuffer is full; cannot write " + len + " characters"); int realLen = Math.min(len, spaceLeft); int firstLen = Math.min(realLen, buffer.length - writePosition); int secondLen = Math.min(realLen - firstLen, buffer.length - markPosition - 1); int written = firstLen + secondLen; for (int i=0; i<firstLen; i++){ buffer[writePosition + i] = str.charAt(off+i); } if (secondLen > 0){ for (int i=0; i<secondLen; i++){ buffer[i] = str.charAt(off+firstLen+i); } writePosition = secondLen; } else { writePosition += written; } if (writePosition == buffer.length) { writePosition = 0; } off += written; len -= written; } if (len > 0){ try { Thread.sleep(100); } catch(Exception x){ throw new IOException("Waiting for available space in buffer interrupted."); } } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -