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 + -
显示快捷键?