The original article was published in JavaIO magical Flush, many of you have read it and I recommend it to the Nuggets.

Contents summary

Java IO stream design had to let a person clap a case to applaud, admire the designer ghost axe natural technique.

If you’re new to Java, I’m sure you’ll get a “giddy” reaction when you first encounter Java IO classes. “It’s not that it’s hard to learn, but it’s so much, and it makes people feel like they don’t know the true face of the mountain. When you finish learning it, you have an Epiphany that you are only in the mountain.

In the days of Java programming, especially in network programming, almost inseparable from Java IO flow, so learn him is very necessary.

For the classification of Java IO streams, you can go to soso and share with you today the magic flush method.

Flush with the OutputStream

Flush () {Flushable (); flush() {Flushable (); flush();

public void flush(a) throws IOException {}Copy the code

Sorry, the implementation is empty. Flush is a null method that does nothing. See, this method is not abstract method, it is a real method. There is nothing in the method body, and everything else is fine! See how the JDK API explains this.

flush 
public void flush(a) throwsIOException flushes this output stream and forces all cached output bytes to be written out. The general convention of Flush is that if the implementation of this output stream has buffered any previously written bytes, calling this method indicates that those bytes should be written immediately to their intended destination. If the intended target of the flow is an abstraction provided by the underlying operating system (such as a file), flushing the flow only guarantees that bytes previously written to the stream will be passed to the operating system for writing, but not that those bytes will actually be written to a physical device (such as a disk drive). The Flush method of OutputStream does nothing. Specifies: Flush in Flushable throws: IOException - if an I/O error occurs.Copy the code

At first, I consoled myself that the class was an abstract class and that its subclasses must have overridden the method.

Well, the direct subclasses of OutputStream are: ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream, etc.

Note: The subclass OutputStream here is from the package org.omg. Corba. portable.

For FileOutputStream, ByteArrayOutputStream, org. Omg. CORBA. Portable. The OutputStream class they flush () method is the parent class method of flush.

The FilterOutputStream class overrides the flush() method, but essentially calls its parent’s Flush () method.

ObjectOutputStream, PipedOutputStream overrides flush().

Let’s take two small examples. The first example mainly writes a string to the text, and the second one writes a certain byte of data to the text.

Example 1: Write a string to text

 import java.io.BufferedOutputStream; 
 import java.io.DataOutputStream; 
 import java.io.File; 
 import java.io.FileOutputStream;
 ​
 public class Test {     
     public static void main(String[] args) throws Exception {       
         File file = new File("text.txt");       
         if(! file.exists()) { file.createNewFile(); } FileOutputStream fos =new FileOutputStream(file);
         BufferedOutputStream bos = new BufferedOutputStream(fos);   
         DataOutputStream dos = new DataOutputStream(fos);
         dos.writeBytes("java io"); }}Copy the code

Example 2: Write a certain byte of data to the text

 import java.io.BufferedOutputStream; 
 import java.io.File; 
 import java.io.FileOutputStream; 
 ​
 public class Test {     
     public static void main(String[] args) throws Exception {       
         File file = new File("text.txt");       
         if(! file.exists()) { file.createNewFile(); } FileOutputStream fos =new FileOutputStream(file);      
         BufferedOutputStream bos = new BufferedOutputStream(fos);       
         byte[] b = new byte[1024*8]; bos.write(b); bos.flush(); }}Copy the code

After these two generations are executed, a 7-byte Java IO file and a 1KB file are generated in the current directory, respectively.

At this point, some people will say, what’s so unusual about that?? Oh, don’t worry!

Now we modify the second code to comment out the call to flush() as follows:

 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 ​
 public class Test {
     public static void main(String[] args) throws Exception {
         File file = new File("text.txt");
         if(! file.exists()) { file.createNewFile(); } FileOutputStream fos =new FileOutputStream(file);
         BufferedOutputStream bos = new BufferedOutputStream(fos);
         byte[] b = new byte[1024];
         bos.write(b);
         //bos.flush();}}Copy the code

OK, run the code again, oh god?? The file size is 0 bytes.

According to?

If you look closely, you will notice that the code in the first example does not call flush() and writes normally. Why not the second one? Or start with the source code to find the answer!

DataOutputStream inherits FilterOutputStream and implements the DataOutput interface. We know that the FilterOutputStream class overrides the flush() method, but essentially calls the parent class’s Flush () method. The flush() method of the DataOutputStream class follows that of its parent, FilterOutputStream:

 public void flush(a) throws IOException {    
     out.flush(); 
 }
Copy the code

So, even if you add dos.flush() to the end of the first example, the result is just as good as if you didn’t, because their parent flush() method is empty, which is why the first code is so magical.

What is the “cause” of the second code? Let’s look at the structure of the BufferedOutputStream class:

 public class BufferedOutputStream extends FilterOutputStream
Copy the code

Take a look at its flush() method:

 public synchronized void flush(a) throws IOException {         
     flushBuffer(); 
     out.flush();
 } 
 ​
 /** Flush the internal buffer */    
 private void flushBuffer(a) throws IOException {   
     if (count > 0) {        
         out.write(buf, 0, count);       
         count = 0; }}Copy the code

Yes, this class overrides the Flush () method, unlike the previous classes that either inherit or copy its parent’s flush() method. The BufferedOutputStream class is a buffering class that implements flush() on its own.

Do you have to flush() when using this class? !!!!! One caveat, however, is that your bytes must not be smaller than 8KB. Example code, note that there is no flush() method.

import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 

public class Test { 	
    public static void main(String[] args) throws Exception { 	
        File file = new File("text.txt"); 		
        if(! file.exists()) { file.createNewFile(); } FileOutputStream fos =new FileOutputStream(file); 		
        BufferedOutputStream bos = new BufferedOutputStream(fos); 		
        byte[] b = new byte[1024*8]; 	
        bos.write(b); 		
        //bos.flush(); }}Copy the code

Executing the code produces an 8KB text file.

Of course, you don’t always know that your data is going to be at least 8KB, so it’s safe to call Flush ().

However, after using up the IO stream (if you have a good habit) we usually call the close() method, which also calls the corresponding flush() method.

As a reminder, if your file is not being read or written as expected, it is probably because you did not call flush() or close().

In addition, most character stream classes implement flush() or close(), but they call the Method of the StreamEncoder class. This class is located under the sun.nio.cs package, and its source code is not available in our JDK.

You can view the source code by clicking streamencoder.java.

Flush with the Writer

Writer is an abstract class declared as follows:

public abstract class Writer implements Appendable.Closeable.Flushable
Copy the code

The Flush () method of the Writer class is an abstract method that subclasses generally implement.

Therefore, a flush() or close() method is usually called after the character stream is used.

abstract public void flush(a) throws IOException;
Copy the code

See the JDK API for details, or the Java source code and the StreamEncoder class above.

This article uses the flush() method in Java IO to explain how important it is to read and think about the source code in a programming language.

In general, no matter what stream (character, byte, buffered stream) technology you are using, you might want to call flush() or close() to prevent data from being written to the output stream.


There is no quick way to learn, keep thinking, practice is king ~