[Re-learning Java Foundation] [JavaIO Stream] [Part.6-2] Stream Decoder and Stream Encoder
StreamDecoder
Summary
This class is under the sun.nio package
In the previous Oracle official JDK, you can only download OpenJDK to see the source code.
Or check it online at grepcode
But since Java 9, Oracle's official jdk has also been developed based on openjdk.
So you can see this kind of source code in jdk1.9
Source code analysis
Member variables
Minimum byte buffer size private static final int MIN_BYTE_BUFFER_SIZE = 32; Default byte buffer size private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192; Whether the byte stream is open or not private volatile boolean isOpen = true; Whether to save the left character flag In order to ensure that the read characters are not scrambled, no less than two characters can be read at a time. If you want to return only one character, you can save the left character until the next return. private boolean haveLeftoverChar = false; Left-sided character private char leftoverChar; character set private Charset cs; A character decoder can convert a sequence of bytes into a 16-bit Unicode sequence according to a specific character set. private CharsetDecoder decoder; Byte buffer private ByteBuffer bb; Converted byte input stream private InputStream in; Readable byte channel private ReadableByteChannel ch;
Construction method constructs StreamDecoder object by inputting byte input stream to lock object character set
StreamDecoder(InputStream in, Object lock, Charset cs) { this(in, lock, cs.newDecoder() //Set the response when encoding character set errors when reading data - Set to replace error characters .onMalformedInput(CodingErrorAction.REPLACE) //Set the response to incompatible character content when reading in data - Set to replace the wrong character .onUnmappableCharacter(CodingErrorAction.REPLACE)); } StreamDecoder(InputStream in, Object lock, CharsetDecoder dec) { super(lock); this.cs = dec.charset(); this.decoder = dec; // Invoke NIO method if input data is fast (input data is file input stream) 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 } StreamDecoder(ReadableByteChannel ch, CharsetDecoder dec, int mbc) { this.in = null; this.ch = ch; this.decoder = dec; this.cs = dec.charset(); this.bb = ByteBuffer.allocate(mbc < 0 ? DEFAULT_BYTE_BUFFER_SIZE : (mbc < MIN_BYTE_BUFFER_SIZE ? MIN_BYTE_BUFFER_SIZE : mbc)); bb.flip(); }
Private read0() method is called inside the read method
public int read() throws IOException { return read0(); } @SuppressWarnings("fallthrough") private int read0() throws IOException { synchronized (lock) { // If there is only one (left high) character, return directly and have Left over Char set false if (haveLeftoverChar) { haveLeftoverChar = false; return leftoverChar; } // Packing more byte data char cb[] = new char[2]; int n = read(cb, 0, 2); switch (n) { //Read and return - 1 case -1: return -1; case 2: leftoverChar = cb[1]; haveLeftoverChar = true; case 1: return cb[0]; default: assert false : n; return -1; } } }