[Re-learning Java Foundation] [JavaIO Stream] [Part.6-2] Stream Decoder and Stream Encoder

Keywords: Java JDK Oracle less

[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

openJDK Online Source

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;
        }
    }
}

StreamEncoder

Source code analysis

Posted by JBS103 on Wed, 06 Feb 2019 11:03:17 -0800