⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 circularcharbuffer.java

📁 it is a basic java browser
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * Circular Character Buffer * Copyright (C) 2002 Stephen Ostermiller * http://ostermiller.org/contact.pl?regarding=Java+Utilities * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * See COPYING.TXT for details. */package com.Ostermiller.util;import java.io.Reader;import java.io.Writer;import java.io.IOException;/** * Implements the Circular Buffer producer/consumer model for characters. * More information about this class is available from <a target="_top" href= * "http://ostermiller.org/utils/CircularCharBuffer.html">ostermiller.org</a>. * <p> * Using this class is a simpler alternative to using a PipedReader * and a PipedWriter. PipedReaders and PipedWriters don't support the * mark operation, don't allow you to control buffer sizes that they use, * and have a more complicated API that requires a instantiating two * classes and connecting them. * <p> * This class is thread safe. * * @see CircularByteBuffer * @see CircularObjectBuffer */public class CircularCharBuffer {	/**	 * The default size for a circular character buffer.	 */	private final static int DEFAULT_SIZE = 1024;	/**	 * A buffer that will grow as things are added.	 */	public final static int INFINITE_SIZE = -1;	/**	 * The circular buffer.	 * <p>	 * The actual capacity of the buffer is one less than the actual length	 * of the buffer so that an empty and a full buffer can be	 * distinguished.  An empty buffer will have the markPostion and the	 * writePosition equal to each other.  A full buffer will have	 * the writePosition one less than the markPostion.	 * <p>	 * There are three important indexes into the buffer:	 * The readPosition, the writePosition, and the markPosition.	 * If the Reader has never been marked, the readPosition and	 * the markPosition should always be the same.  The characters	 * available to be read go from the readPosition to the writePosition,	 * wrapping around the end of the buffer.  The space available for writing	 * goes from the write position to one less than the markPosition,	 * wrapping around the end of the buffer.  The characters that have	 * been saved to support a reset() of the Reader go from markPosition	 * to readPosition, wrapping around the end of the buffer.	 */	protected char[] buffer;	/**	 * Index of the first character available to be read.	 */	protected volatile int readPosition = 0;	/**	 * Index of the first character available to be written.	 */	protected volatile int writePosition = 0;	/**	 * Index of the first saved character. (To support stream marking.)	 */	protected volatile int markPosition = 0;	/**	 * Number of characters that have to be saved	 * to support mark() and reset() on the Reader.	 */	protected volatile int markSize = 0;	/**	 * If this buffer is infinite (should resize itself when full)	 */	protected volatile boolean infinite = false;	/**	 * True if a write to a full buffer should block until the buffer	 * has room, false if the write method should throw an IOException	 */	protected boolean blockingWrite = true;	/**	 * The Reader that can empty this buffer.	 */	protected Reader reader = new CircularCharBufferReader();	/**	 * true if the close() method has been called on the Reader	 */	protected boolean readerClosed = false;	/**	 * The Writer that can fill this buffer.	 */	protected Writer writer = new CircularCharBufferWriter();	/**	 * true if the close() method has been called on the writer	 */	protected boolean writerClosed = false;	/**	 * Make this buffer ready for reuse.  The contents of the buffer	 * will be cleared and the streams associated with this buffer	 * will be reopened if they had been closed.	 */	public void clear(){		synchronized (this){			readPosition = 0;			writePosition = 0;			markPosition = 0;			readerClosed = false;			writerClosed = false;		}	}	/**	 * Retrieve a Writer that can be used to fill	 * this buffer.	 * <p>	 * Write methods may throw a BufferOverflowException if	 * the buffer is not large enough.  A large enough buffer	 * size must be chosen so that this does not happen or	 * the caller must be prepared to catch the exception and	 * try again once part of the buffer has been consumed.	 *	 *	 * @return the producer for this buffer.	 */	public Writer getWriter(){		return writer;	}	/**	 * Retrieve a Reader that can be used to empty	 * this buffer.	 * <p>	 * This Reader supports marks at the expense	 * of the buffer size.	 *	 * @return the consumer for this buffer.	 */	public Reader getReader(){		return reader;	}	/**	 * Get number of characters that are available to be read.	 * <p>	 * Note that the number of characters available plus	 * the number of characters free may not add up to the	 * capacity of this buffer, as the buffer may reserve some	 * space for other purposes.	 *	 * @return the size in characters of this buffer	 */	public int getAvailable(){		synchronized (this){			return available();		}	}	/**	 * Get the number of characters this buffer has free for	 * writing.	 * <p>	 * Note that the number of characters available plus	 * the number of characters free may not add up to the	 * capacity of this buffer, as the buffer may reserve some	 * space for other purposes.	 *	 * @return the available space in characters of this buffer	 */	public int getSpaceLeft(){		synchronized (this){			return spaceLeft();		}	}	/**	 * Get the capacity of this buffer.	 * <p>	 * Note that the number of characters available plus	 * the number of characters free may not add up to the	 * capacity of this buffer, as the buffer may reserve some	 * space for other purposes.	 *	 * @return the size in characters of this buffer	 */	public int getSize(){		synchronized (this){			return buffer.length;		}	}	/**	 * double the size of the buffer	 */	private void resize(){		char[] newBuffer = new char[buffer.length * 2];		int marked = marked();		int available = available();		if (markPosition <= writePosition){			// any space between the mark and			// the first write needs to be saved.			// In this case it is all in one piece.			int length = writePosition - markPosition;			System.arraycopy(buffer, markPosition, newBuffer, 0, length);		} else {			int length1 = buffer.length - markPosition;			System.arraycopy(buffer, markPosition, newBuffer, 0, length1);			int length2 = writePosition;			System.arraycopy(buffer, 0, newBuffer, length1, length2);		}		buffer = newBuffer;		markPosition = 0;		readPosition = marked;		writePosition = marked + available;	}	/**	 * Space available in the buffer which can be written.	 */	private int spaceLeft(){		if (writePosition < markPosition){			// any space between the first write and			// the mark except one character is available.			// In this case it is all in one piece.			return (markPosition - writePosition - 1);		} else {			// space at the beginning and end.			return ((buffer.length - 1) - (writePosition - markPosition));		}	}	/**	 * Characters available for reading.	 */	private int available(){		if (readPosition <= writePosition){			// any space between the first read and			// the first write is available.  In this case i			// is all in one piece.			return (writePosition - readPosition);		} else {			// space at the beginning and end.			return (buffer.length - (readPosition - writePosition));		}	}	/**	 * Characters saved for supporting marks.	 */	private int marked(){		if (markPosition <= readPosition){			// any space between the markPosition and			// the first write is marked.  In this case i			// is all in one piece.			return (readPosition - markPosition);		} else {			// space at the beginning and end.			return (buffer.length - (markPosition - readPosition));		}	}	/**	 * If we have passed the markSize reset the	 * mark so that the space can be used.	 */	private void ensureMark(){		if (marked() >= markSize){			markPosition = readPosition;			markSize = 0;		}	}	/**	 * Create a new buffer with a default capacity.	 * Writing to a full buffer will block until space	 * is available rather than throw an exception.	 */	public CircularCharBuffer(){		this (DEFAULT_SIZE, true);	}	/**	 * Create a new buffer with given capacity.	 * Writing to a full buffer will block until space	 * is available rather than throw an exception.	 * <p>	 * Note that the buffer may reserve some characters for	 * special purposes and capacity number of characters may	 * not be able to be written to the buffer.	 * <p>	 * Note that if the buffer is of INFINITE_SIZE it will	 * neither block or throw exceptions, but rather grow	 * without bound.	 *	 * @param size desired capacity of the buffer in characters or CircularCharBuffer.INFINITE_SIZE	 */	public CircularCharBuffer(int size){		this (size, true);	}	/**	 * Create a new buffer with a default capacity and	 * given blocking behavior.	 *	 * @param blockingWrite true writing to a full buffer should block	 *        until space is available, false if an exception should	 *        be thrown instead.	 */	public CircularCharBuffer(boolean blockingWrite){		this (DEFAULT_SIZE, blockingWrite);	}	/**	 * Create a new buffer with the given capacity and	 * blocking behavior.	 * <p>	 * Note that the buffer may reserve some characters for	 * special purposes and capacity number of characters may	 * not be able to be written to the buffer.	 * <p>	 * Note that if the buffer is of CircularCharBuffer.INFINITE_SIZE it will	 * neither block or throw exceptions, but rather grow	 * without bound.	 *	 * @param size desired capacity of the buffer in characters or CircularCharBuffer.INFINITE_SIZE	 * @param blockingWrite true writing to a full buffer should block	 *        until space is available, false if an exception should	 *        be thrown instead.	 */	public CircularCharBuffer(int size, boolean blockingWrite){		if (size == INFINITE_SIZE){			buffer = new char[DEFAULT_SIZE];			infinite = true;		} else {			buffer = new char[size];			infinite = false;		}		this.blockingWrite = blockingWrite;	}	/**	 * Class for reading from a circular character buffer.	 */	protected class CircularCharBufferReader extends Reader {		/**		 * 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.		 *		 * @throws IOException never.		 */		public void close() throws IOException {			synchronized (CircularCharBuffer.this){				readerClosed = true;			}		}		/**		 * Mark the present position in the stream. Subsequent calls to reset() will		 * attempt to reposition the stream to this point.		 * <p>		 * The readAheadLimit must be less than the size of circular buffer.		 *		 * @param readAheadLimit Limit on the number of characters that may be read while		 *    still preserving the mark. After reading this many characters, attempting to		 *    reset the stream will fail.		 * @throws IOException if the stream is closed, or the buffer size is greater		 * than or equal to the readAheadLimit.		 */		public void mark(int readAheadLimit) throws IOException {			synchronized (CircularCharBuffer.this){				if (readerClosed) throw new IOException("Reader has been closed; cannot mark a closed Reader.");				if (buffer.length - 1 <= readAheadLimit) throw new IOException("Cannot mark stream, readAheadLimit bigger than buffer size.");				markSize = readAheadLimit;				markPosition = readPosition;			}		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -