java IO: Stream Encoder Addendum

Keywords: PHP Attribute encoding

Here are three more methods: flushLeftoverChar(), writeBytes(), close().

I. Flush Left over Char ()

    private void flushLeftoverChar(CharBuffer var1, boolean var2) throws IOException {
        if (this.haveLeftoverChar || var2) {
            if (this.lcb == null) {
                this.lcb = CharBuffer.allocate(2);
            } else {
                this.lcb.clear();
            }

            if (this.haveLeftoverChar) {
                this.lcb.put(this.leftoverChar);
            }

            if (var1 != null && var1.hasRemaining()) {
                this.lcb.put(var1.get());
            }

            this.lcb.flip();

            while(this.lcb.hasRemaining() || var2) {
                CoderResult var3 = this.encoder.encode(this.lcb, this.bb, var2);
                if (var3.isUnderflow()) {
                    if (this.lcb.hasRemaining()) {
                        this.leftoverChar = this.lcb.get();
                        if (var1 != null && var1.hasRemaining()) {
                            this.flushLeftoverChar(var1, var2);
                        }

                        return;
                    }
                    break;
                }

                if (var3.isOverflow()) {
                    assert this.bb.position() > 0;

                    this.writeBytes();
                } else {
                    var3.throwException();
                }
            }

            this.haveLeftoverChar = false;
        }
    }

var1 is a character buffer, var2 is called false, and leftoverChar and haveLeftoverChar are attribute fields of this kind. The following is a flowchart:

2. WteBytes ():

This method is the real way to output data to the computer (previously there was only a buffer, not really output to the local computer)

 private void writeBytes() throws IOException {
        this.bb.flip();
        int var1 = this.bb.limit();
        int var2 = this.bb.position();

        assert var2 <= var1;

        int var3 = var2 <= var1 ? var1 - var2 : 0;
        if (var3 > 0) {
            if (this.ch != null) {
                assert this.ch.write(this.bb) == var3 : var3;
            } else {
                this.out.write(this.bb.array(), this.bb.arrayOffset() + var2, var3);
            }
        }

        this.bb.clear();
    }

Here we flip the byte buffer first (because we used to put data in the character buffer, and now we need to take out the output), then judge the legitimacy of position and limit position in bb. If it is correct, we use channel or not use channel output (channel is preferred to use channel) and empty BB after output for the next one. Secondary filling.

3. close():

In fact, we can see that in some cases of implwrite() and flushLeftoverChar, the output is not directly using writeBytes(), then the character coded after the method call is still in the byte buffer and not exported to the local, so when using the output stream of write class, we must not forget to close it at last. The close() method of the output stream outputs the remaining data in the byte buffer to the local file. If not invoked, the output may have little or no data at all! Here is an example:

public class Test  {
    public static void main(String[] args) {
        File file = new File("D:\\img\\test.txt");
        try {
            OutputStreamWriter writer = new FileWriter(file,true);
            String s = "Chinese";
            writer.write(s);
            //writer.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        catch (IOException e){
            e.printStackTrace();
        }
        System.out.println();
    }
}

If close is commented out here, it runs after:

You can see that the text document is empty, and after calling close(), look at the text document:

At this time, the output will be normal.

public void close() throws IOException {
        synchronized(this.lock) {
            if (this.isOpen) {
                this.implClose();
                this.isOpen = false;
            }
        }
    }

The close() method essentially calls implClose():

void implClose() throws IOException {
        this.flushLeftoverChar((CharBuffer)null, true);

        try {
            while(true) {
                CoderResult var1 = this.encoder.flush(this.bb);
                if (var1.isUnderflow()) {
                    if (this.bb.position() > 0) {
                        this.writeBytes();
                    }

                    if (this.ch != null) {
                        this.ch.close();
                    } else {
                        this.out.close();
                    }

                    return;
                }

                if (var1.isOverflow()) {
                    assert this.bb.position() > 0;

                    this.writeBytes();
                } else {
                    var1.throwException();
                }
            }
        } catch (IOException var2) {
            this.encoder.reset();
            throw var2;
        }
    }

You can see that this method makes another encoding decision and calls the writeBytes() method to output all the contents of the byte buffer, which is why close() must be called. (The method also outputs leftoverChar, which is judged at the beginning of the method.)

Posted by ns1025 on Fri, 19 Jul 2019 03:31:14 -0700