Bug in BufferedReader.ready()

Archie Cobbs archie at whistle.com
Thu Dec 3 16:12:48 PST 1998


Artur Biesiadowski writes:
> is:
> 	if ( size > 0 || rd.ready() )
> should be:
> 	if ( size > pos || rd.ready() )
> (or size > pos +1 ?)

Yes, this is a bug. Could you try the version of BufferedReader.java
below and let me know if it works for your application? You will have
to rebuild and reinstall Klasses.jar.

Thanks,
-Archie

___________________________________________________________________________
Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com

/*
 * Java core library component.
 *
 * Copyright (c) 1997, 1998
 *      Transvirtual Technologies, Inc.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file.
 */

package java.io;


public class BufferedReader
  extends Reader
{
	final private static int DEFAULTBUFFERSIZE = 1024;
	private Reader rd;
	private char[] inbuf;
	private int pos;	// position of next char in buffer
	private int size;	// total length of valid chars in buffer
	private boolean markset;

public BufferedReader(Reader in) {
	this(in, DEFAULTBUFFERSIZE);
}

public BufferedReader(Reader in, int sz) {
	rd = in;
	inbuf = new char[sz];
	pos = 0;
	size = 0;
	markset = false;
}

public void close() throws IOException {
	rd.close();
}

public void mark(int readAheadLimit) throws IOException {
	synchronized(lock) {
		char[] oldbuf = inbuf;

		// Allocate bigger buffer if necessary
		if (readAheadLimit > inbuf.length) {
			inbuf = new char[readAheadLimit];
		}

		// Shift data to the beginning of the buffer
		System.arraycopy(oldbuf, pos, inbuf, 0, size - pos);
		size -= pos;
		pos = 0;
		markset = true;
	}
}

public boolean markSupported() {
	return (true);
}

protected void pushback() {
	pos--;
}

public int read () throws IOException {
	synchronized ( lock ) {
		if (pos < size || refillBuffer() > 0) {
			return (inbuf[pos++]);
		}
		return (-1);
	}
}

public int read ( char cbuf[], int off, int len ) throws IOException {
	synchronized(lock) {

		// Do read directly in this case, according to JDK 1.2 docs
		if (pos == size && !markset && len >= inbuf.length) {
			return rd.read(cbuf, off, len);
		}

		int nread, chunk;
		for (nread = 0; nread < len; nread += chunk) {

			// Make sure there's something in the buffer
			if (pos == size) {
				// Avoid unneccesary blocking
				if (nread > 0 && !rd.ready()) {
					return nread;
				}
				// Try to fill buffer
				if (refillBuffer() <= 0) {
					return (nread > 0) ? nread : -1;
				}
			}

			// Copy next chunk of chars from buffer to output array
			chunk = len - nread;
			if (chunk > size) {
				chunk = size;
			}
			System.arraycopy(inbuf, pos, cbuf, off, chunk);
			pos += chunk;
			off += chunk;
		}
		return (nread);
	}
}

public String readLine () throws IOException {
	int     start = pos;
	char    c = ' ';    // silly javac, complains about initialization
	String  s = null;

	synchronized ( lock ) {
		while ( true ) {

			// Find next newline or carriage return
			while (pos < size
				&& (c = inbuf[pos]) != '\n' && c != '\r')
			    pos++;

			// Did we see one?
			if (pos == size) {	// nothing found yet
				if (pos > start) {
					if (s == null) {
						s = new String(inbuf, start, pos-start);
					}
					else {
						s += new String(inbuf, start, pos-start);
					}
				}
				if (refillBuffer() <= 0) {
					return (s);
				}
				start = 0;
			}
			else {			// we got a line terminator
				if ( s == null ) {
					s = new String(inbuf, start, pos-start);
				}
				else {
					s += new String(inbuf, start, pos-start);
				}
				pos++;
				if (c == '\r') {
					if (read() != '\n' && pos > 0) {
						pos--;  // skip over "\r\n"
					}
				}
				return (s);
			}
		}
	}
}

public boolean ready() throws IOException {
	synchronized(lock) {
		if (pos < size || rd.ready()) {
			return (true);
		}
		else {
			return (false);
		}
	}
}

private int refillBuffer () throws IOException {
	synchronized ( lock ) {
		int n;

		n = rd.read( inbuf, 0, inbuf.length);
		pos = 0;
		markset = false;

		if (n > 0) {
			size = n;
			return (n);
		}
		else {
			size = 0;
			return (-1);
		}
	}
}

public void reset() throws IOException {
	synchronized(lock) {
		if (!markset) {
			throw new IOException("invalid mark");
		}
		pos = 0;	// reset to the beginning of the buffer
	}
}

public long skip(long n) throws IOException {
	synchronized(lock) {
		long bufskip;

		// Skip from within the buffer first
		bufskip = size - pos;
		if (bufskip > n) {
			bufskip = n;
		}
		pos += (int)bufskip;		// cast is OK

		// Anything more to skip?
		if (bufskip == n) {
			return n;
		}

		// Reset buffer and skip what remains directly
		pos = 0;
		size = 0;
		markset = false;
		return bufskip + rd.skip(n - bufskip);
	}
}
}


More information about the kaffe mailing list