publicintread(char cbuf[], int offset, int length)throws IOException { // 创建两个临时变量,避免直接修改参数 int off = offset; int len = length; // 加锁 synchronized (lock) { // 检查自己是否已开启,如果没有则抛出异常 ensureOpen(); // 检查输出参数是否无效,无效则抛出异常 if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { thrownew IndexOutOfBoundsException(); } // 如果读取长度为 0,则直接返回 0 if (len == 0) return0;
// 如上次读取的 2 个 byte 不是双字节字符,则这个值会被设置为 1 来防止返回值计算错误 int n = 0;
// 如上次读取的 2 个 byte 不是双字节字符 if (haveLeftoverChar) { // 将上次读取的两个 byte 的后面的一个保存到返回值数组的第一个位置 // Copy the leftover char into the buffer cbuf[off] = leftoverChar; // 因为已经读取了一个字符,所以起始地址增加 1,长度减少 1 off++; len--; // 因为已经用过了上次读取的两个 byte 中后面的一个,所以上次取消设置这个标志位 haveLeftoverChar = false; // 已经读取了一个字符,将这个值设置为 1 来防止返回值计算错误 n = 1; // 如果还需读取的长度为 0,或尚未准备好读取,则直接返回已读长度(1) if ((len == 0) || !implReady()) // Return now if this is all we can produce w/o blocking return n; }
// 如果还需读取的字符长度为 1 if (len == 1) { // 调用 read0 读取一个字符 // Treat single-character array reads just like read() int c = read0(); // 如果读取失败,则根据 n 的值确定返回失败还是 n if (c == -1) return (n == 0) ? -1 : n; // 保存读取到的字符 cbuf[off] = (char)c; // 返回读取长度 return n + 1; }
// 调用 implRead 来读取更多字符 return n + implRead(cbuf, off, off + len); } }
intimplRead(char[] cbuf, int off, int end)throws IOException { // 如果要读取的长度 <= 0,则抛出异常 // In order to handle surrogate pairs, this method requires that // the invoker attempt to read at least two characters. Saving the // extra character, if any, at a higher level is easier than trying // to deal with it here. assert (end - off > 1);
// 创建保存结果的容器 CharBuffer cb = CharBuffer.wrap(cbuf, off, end - off); if (cb.position() != 0) // Ensure that cb[0] == cbuf[off] cb = cb.slice();
// 是否已经读到结尾的标志位 boolean eof = false; for (;;) { // 对输入缓冲区中的字符进行解码 CoderResult cr = decoder.decode(bb, cb, eof); // 如果是因为 Underflow 结束的解码 if (cr.isUnderflow()) { // 如果已经读到结尾则跳出循环 if (eof) break; // 如果输出保存结果的容器已经没有剩余空间则跳出循环 if (!cb.hasRemaining()) break; // 如果已经读了一些数据,且尚未准备好继续读取,则跳出循环 if ((cb.position() > 0) && !inReady()) break; // Block at most once // 刷新输入缓冲区 int n = readBytes(); if (n < 0) { eof = true; if ((cb.position() == 0) && (!bb.hasRemaining())) break; decoder.reset(); } continue; } // 如果输出缓冲区没有更多的空间则跳出循环 if (cr.isOverflow()) { assert cb.position() > 0; break; } cr.throwException(); }
// 如果已经读到结尾则重置解码器 if (eof) { // ## Need to flush decoder decoder.reset(); }
// 如果一个字也没读出来,则返回读取失败 if (cb.position() == 0) { if (eof) return -1; assertfalse; } // 返回读取长度 return cb.position(); }
// This path disabled until direct buffers are faster if (false && in instanceof FileInputStream) { ch = getChannel((FileInputStream)in); if (ch != null) bb = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE); } if (ch == null) { this.in = in; this.ch = null; bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE); } bb.flip(); // So that bb is initially empty }