简单来说,无论你调用FileReader还是InputStreamReader的read()方法,其本质都是调用StreamDecoder的read()方法。
而read()会去调用read0(),read0()简单来说做了两件事,一个是调用read(char cbuf[], int offset, int length),其二是决定直接返回cbuf[0]还是将cbuf[1]赋值到leftoverChar再返回cbuf[0],haveLeftoverChar为true时,直接返回leftoverChar然后将其置为false。如果调用read返回-1,则表示已经读取到文件末尾,此时该read0()也会返回-1。
read(char cbuf[], int offset, int length):
这个方法用来调用方法读取字符到cbuf[]中,并返回实际读取到的字符数。
public int read(char[] var1, int var2, int var3) throws IOException { int var4 = var2; int var5 = var3; synchronized(this.lock) { this.ensureOpen(); if (var4 >= 0 && var4 <= var1.length && var5 >= 0 && var4 + var5 <= var1.length && var4 + var5 >= 0) { if (var5 == 0) { return 0; } else { byte var7 = 0; if (this.haveLeftoverChar) { var1[var4] = this.leftoverChar; ++var4; --var5; this.haveLeftoverChar = false; var7 = 1; if (var5 == 0 || !this.implReady()) { return var7; } } if (var5 == 1) { int var8 = this.read0(); if (var8 == -1) { return var7 == 0 ? -1 : var7; } else { var1[var4] = (char)var8; return var7 + 1; } } else { return var7 + this.implRead(var1, var4, var4 + var5); } } } else { throw new IndexOutOfBoundsException(); } } }
由于在read0()中是这么调用read的:
int var3 = this.read(var2, 0, 2);
且调用前已经判断了haveLeftOverChar并当其为true时会将其置成false,所以此方法在被read0()调用时本质是调用implRead():
int implRead(char[] var1, int var2, int var3) throws IOException { assert var3 - var2 > 1; CharBuffer var4 = CharBuffer.wrap(var1, var2, var3 - var2); if (var4.position() != 0) { var4 = var4.slice(); } boolean var5 = false; while(true) { CoderResult var6 = this.decoder.decode(this.bb, var4, var5); if (var6.isUnderflow()) { if (var5 || !var4.hasRemaining() || var4.position() > 0 && !this.inReady()) { break; } int var7 = this.readBytes(); if (var7 < 0) { var5 = true; if (var4.position() == 0 && !this.bb.hasRemaining()) { break; } this.decoder.reset(); } } else { if (var6.isOverflow()) { assert var4.position() > 0; break; } var6.throwException(); } } if (var5) { this.decoder.reset(); } if (var4.position() == 0) { if (var5) { return -1; } assert false; } return var4.position(); }
这里的var1便是cbuf[],var2是0,var3是2,var4是根据cbuf[]创建的字符缓冲区,两者会同步改变,var5代表eof,var6是调用解码方法后返回的状态(CodeResult)。接着调用解码方法,该方法会把字节流bb里的数据解码成字符并填充到var4(即cbuf[])中,然后返回var6。对var6进行判断,如果是underflow,那代表解码器已经将字节流里的剩余数据全部解码到var4(cbuf[])中,这时候要判断是否还是输入(eof),如果还有输入,就要调用readBytes并返回状态,如果返回-1则表示已经eof,将eof置为true以便下次调用判断eof。如果var6状态时overflow,那说明var4(cbuf[])已满而字节流还有剩余,这时候跳出循环,进行一系列安全判断后返回var4.position()(即已读取的字符个数,因为position()返回的是下一个要被读或写的元素的索引,所以[0],[1]都被读写后,返回的就是2,即已读取2个字符,且两个字符就位于cbuf[]中)。