bufferedreader.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 502 行 · 第 1/2 页

JAVA
502
字号
	  * @param buf The array into which the chars read should be stored
	  * @param offset The offset into the array to start storing chars
	  * @param count The requested number of chars to read
	  *
	  * @return The actual number of chars read, or -1 if end of stream.
	  *
	  * @exception IOException If an error occurs.
	  */
	public int read(char[] buf, int offset, int count) throws IOException {
		synchronized (lock) {
			checkStatus();
			// Once again, we need to handle the special case of a readLine
			// that has a '\r' at the end of the buffer.  In this case, we'll
			// need to skip a '\n' if it is the next char to be read.
			// This special case is indicated by 'pos > limit'.
			boolean retAtEndOfBuffer = false;

			int avail = limit - pos;
			if (count > avail) {
				if (avail > 0)
					count = avail;
				else // pos >= limit
					{
					if (limit == buffer.length)
						markPos = -1; // read too far - invalidate the mark.
					if (pos > limit) {
						// Set a boolean and make pos == limit to simplify things.
						retAtEndOfBuffer = true;
						--pos;
					}
					if (markPos < 0) {
						// Optimization:  can read directly into buf.
						if (count >= buffer.length && !retAtEndOfBuffer)
							return in.read(buf, offset, count);
						pos = limit = 0;
					}
					avail = in.read(buffer, limit, buffer.length - limit);
					if (retAtEndOfBuffer
						&& avail > 0
						&& buffer[limit] == '\n') {
						--avail;
						limit++;
					}
					if (avail < count) {
						if (avail <= 0)
							return avail;
						count = avail;
					}
					limit += avail;
				}
			}
			System.arraycopy(buffer, pos, buf, offset, count);
			pos += count;
			return count;
		}
	}

	/* Read more data into the buffer.  Update pos and limit appropriately.
	   Assumes pos==limit initially.  May invalidate the mark if read too much.
	   Return number of chars read (never 0), or -1 on eof. */
	private int fill() throws IOException {
		checkStatus();
		// Handle the special case of a readLine that has a '\r' at the end of
		// the buffer.  In this case, we'll need to skip a '\n' if it is the
		// next char to be read.  This special case is indicated by 'pos > limit'.
		boolean retAtEndOfBuffer = false;
		if (pos > limit) {
			retAtEndOfBuffer = true;
			--pos;
		}

		if (markPos >= 0 && limit == buffer.length)
			markPos = -1;
		if (markPos < 0)
			pos = limit = 0;
		int count = in.read(buffer, limit, buffer.length - limit);
		if (count > 0)
			limit += count;

		if (retAtEndOfBuffer && buffer[pos] == '\n') {
			--count;
			// If the mark was set to the location of the \n, then we
			// must change it to fully pretend that the \n does not
			// exist.
			if (markPos == pos)
				++markPos;
			++pos;
		}

		return count;
	}

	public int read() throws IOException {
		synchronized (lock) {
			checkStatus();
			if (pos >= limit && fill() <= 0)
				return -1;
			return buffer[pos++];
		}
	}

	/* Return the end of the line starting at this.pos and ending at limit.
	 * The index returns is *before* any line terminators, or limit
	 * if no line terminators were found.
	 */
	private int lineEnd(int limit) {
		int i = pos;
		for (; i < limit; i++) {
			char ch = buffer[i];
			if (ch == '\n' || ch == '\r')
				break;
		}
		return i;
	}

	/**
	  * This method reads a single line of text from the input stream, returning
	  * it as a <code>String</code>.  A line is terminated by "\n", a "\r", or
	  * an "\r\n" sequence.  The system dependent line separator is not used.
	  * The line termination characters are not returned in the resulting
	  * <code>String</code>.
	  * 
	  * @return The line of text read, or <code>null</code> if end of stream.
	  * 
	  * @exception IOException If an error occurs
	  */
	public String readLine() throws IOException {
		checkStatus();
		// Handle the special case where a previous readLine (with no intervening
		// reads/skips) had a '\r' at the end of the buffer.
		// In this case, we'll need to skip a '\n' if it's the next char to be read.
		// This special case is indicated by 'pos > limit'.
		if (pos > limit) {
			int ch = read();
			if (ch < 0)
				return null;
			if (ch != '\n')
				--pos;
		}
		int i = lineEnd(limit);
		if (i < limit) {
			String str = new String(buffer, pos, i - pos);
			pos = i + 1;
			// If the last char in the buffer is a '\r', we must remember
			// to check if the next char to be read after the buffer is refilled
			// is a '\n'.  If so, skip it.  To indicate this condition, we set pos
			// to be limit + 1, which normally is never possible.
			if (buffer[i] == '\r')
				if (pos == limit || buffer[pos] == '\n')
					pos++;
			return str;
		}
		StringBuffer sbuf = new StringBuffer(200);
		sbuf.append(buffer, pos, i - pos);
		pos = i;
		// We only want to return null when no characters were read before
		// EOF.  So we must keep track of this separately.  Otherwise we
		// would treat an empty `sbuf' as an EOF condition, which is wrong
		// when there is just a newline.
		boolean eof = false;
		for (;;) {
			int ch = read();
			if (ch < 0) {
				eof = true;
				break;
			}
			if (ch == '\n' || ch == '\r') {
				// Check here if a '\r' was the last char in the buffer; if so,
				// mark it as in the comment above to indicate future reads
				// should skip a newline that is the next char read after
				// refilling the buffer.
				if (ch == '\r')
					if (pos == limit || buffer[pos] == '\n')
						pos++;
				break;
			}
			i = lineEnd(limit);
			sbuf.append(buffer, pos - 1, i - (pos - 1));
			pos = i;
		}
		return (sbuf.length() == 0 && eof) ? null : sbuf.toString();
	}

	/**
	  * This method skips the specified number of chars in the stream.  It
	  * returns the actual number of chars skipped, which may be less than the
	  * requested amount.
	  * <p>
	  * This method first discards chars in the buffer, then calls the
	  * <code>skip</code> method on the underlying stream to skip the remaining chars.
	  *
	  * @param num_chars The requested number of chars to skip
	  *
	  * @return The actual number of chars skipped.
	  *
	  * @exception IOException If an error occurs
	  */
	public long skip(long count) throws IOException {
		synchronized (lock) {
			checkStatus();
			if (count <= 0)
				return 0;
			// Yet again, we need to handle the special case of a readLine
			// that has a '\r' at the end of the buffer.  In this case, we need
			// to ignore a '\n' if it is the next char to be read.
			// This special case is indicated by 'pos > limit' (i.e. avail < 0).
			// To simplify things, if we're dealing with the special case for
			// readLine, just read the next char (since the fill method will
			// skip the '\n' for us).  By doing this, we'll have to back up pos.
			// That's easier than trying to keep track of whether we've skipped
			// one element or not.
			int ch;
			if (pos > limit)
				if ((ch = read()) < 0)
					return 0;
				else
					--pos;

			int avail = limit - pos;

			if (count < avail) {
				pos += count;
				return count;
			}

			pos = limit;
			long todo = count - avail;
			if (todo > buffer.length) {
				markPos = -1;
				todo -= in.skip(todo);
			} else {
				while (todo > 0) {
					avail = fill();
					if (avail <= 0)
						break;
					if (avail > todo)
						avail = (int)todo;
					pos += avail;
					todo -= avail;
				}
			}
			return count - todo;
		}
	}

	private void checkStatus() throws IOException {
		if (in == null)
			throw new IOException("Stream closed");
	}
}

⌨️ 快捷键说明

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