The correct way to close IO stream in JAVA

Writing 1: Close the stream in try instead of finally

try {
    OutputStream out = new FileOutputStream("file");
    // ...operation flow code
    out.close();
} catch (Exception e) {
    e.printStackTrace();
}

When the operation stream code reports an error, this writing method will cause the stream to not be closed normally, so it is not recommended!

The correct operation method should be completed in finally. The example code is as follows:

OutputStream out = null;
try {
    out = new FileOutputStream("file");
    // ...operation flow code
} catch (Exception e) {
    e.printStackTrace();
} finally {
    // Close in finally to ensure it can be executed
    try {
        if (out != null) {
            out.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Writing 2: When closing multiple streams, put them in a try

When closing multiple streams, some students find it troublesome and put it in a try. The example code is as follows:

OutputStream out1 = null;
OutputStream out2 = null;
try {
    out1 = new FileOutputStream("file");
    out2 = new FileOutputStream("file");
    // ...operation flow code
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if (out1 != null) {
            // If an exception occurs here, the out2 stream is not closed
            out1.close();
        }
        if (out2 != null) {
            out2.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

In this way of writing, when out1.close throws an exception, out2.close will not be closed normally, so it is not recommended !

The correct operation method should be to close one by one. Don’t be lazy. The example code is as follows:

OutputStream out1 = null;
OutputStream out2 = null;
try {
    out1 = new FileOutputStream("file");
    out2 = new FileOutputStream("file");
    // ...operation flow code
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if (out1 != null) {
            out1.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (out2 != null) {
            out2.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Writing method 3: Create the stream in the loop and close it outside the loop

Some students close the file stream outside the loop when operating multiple files in a loop. The example code is as follows:

OutputStream out = null;
try {
    for (int i = 0; i < 10; i + + ) {
        out = new FileOutputStream("file");
        // ...operation flow code
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        if (out != null) {
            out.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

On the surface, there seems to be no problem, but in fact 10 IO streams are created. After the logic in try is executed, only the last IO stream object is assigned to the out parameter. That is, after the program is executed, only the last IO stream is closed, and the other 9 IO streams are useless and manually closed, so it is not recommended!

The correct operation method should be close in the loop body. Don’t be lazy. The example code is as follows:

for (int i = 0; i < 10; i + + ) {
    OutputStream out = null;
    try {
        out = new FileOutputStream("file");
        // ...operation flow code
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (out != null) {
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Writing method 4: When closing multiple streams, there is no need to follow the define-first-release principle

When some students operate multiple file streams, after the operation is completed, they close the file streams in order. The example code is as follows:

FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
    fos = new FileOutputStream("file");
    bos = new BufferedOutputStream(fos);
    // ...operation flow code
} catch (Exception e){

} finally {
    //Close the streams one by one
    try {
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        // java.io.IOException: Stream Closed error will be reported here
        bos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Close the file stream in order. In this way, java.io.IOException: Stream Closed error may be reported.

The reason is that BufferedOutputStream depends on FileOutputStream. If you close the FileOutputStream stream directly and then close BufferedOutputStream again, you will be prompted that the source has been Closed, buffer data cannot be output.

The correct operation method should follow the principle of define later and release first. The example code is as follows:

FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
    fos = new FileOutputStream("file");
    bos = new BufferedOutputStream(fos);
    // ...operation flow code
} catch (Exception e){

} finally {
    // Define later and release first
    try {
        bos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Writing method 5: jdk7 and above, it is recommended to use try-with-resources writing method

try-with-resources is a new exception handling mechanism introduced in JDK 7, which allows developers to avoid explicitly releasing the resources used in the try-catch statement block. resource.

Taking the above example, it can be changed to the following writing:

try (FileOutputStream fos = new FileOutputStream("file");
     BufferedOutputStream bos = new BufferedOutputStream(fos)){
    // ...operation flow code
} catch (Exception e){
    e.printStackTrace();
}

try-with-resourcesThe operation of releasing resources also follows the principle of release first after definition!

Writing method 6: When using the packaging flow, you only need to close the last packaging flow

Packaging stream refers to the IO stream class implemented through the decoration design pattern. Its purpose is to extend the functions of the underlying stream. When actual data is transmitted, the underlying stream is still used for transmission. For example, the buffered byte output stream BufferedOutputStream is a wrapper stream. Its purpose is to provide a buffer function for the byte output stream to make data output more efficient.

When using the packaging flow, we only need to close the last packaging flow.

Taking the above as an example, the rewritten example code is as follows:

InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
    is = new FileInputStream("file");
    isr = new InputStreamReader(is);
    br = new BufferedReader(isr);
    // ...operation flow code
} catch (Exception e){
    e.printStackTrace();
} finally {
    //Closing the wrapper stream will also automatically close the InputStream stream
    try {
        br.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Summarize:

In the above, we mentioned that as long as it is an IO stream, it is recommended that everyone close the resource on the mobile phone. However, there is a stream in Java that does not need to be closed manually, such as the memory read and write stream: ByteArrayInputStream, ByteArrayOutputStream.

Different from streams pointing to the hard disk, ByteArrayInputStream and ByteArrayOutputStream are actually byte arrays disguised as streams stored in memory (just think of them as byte data) , they will not lock any file handles and ports, and if no longer used, the byte array will be garbage collected, so there is no need to close it.

When the IO stream points to external resources such as memory card/hard disk/network, it must be closed manually.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 138778 people are learning the system