user1921479
user1921479

Reputation: 255

Try-with-resources should be used

How to convert below code to JAVA 8 - try-with-resource. I have written this code in java 6,i have upgraded java 6 to java 8 - Sonar giving Blocker message "Try-with-resources should be used"

 public void archivingTheFile(String zipFile){
    byte[] buffer = new byte[1024];
    try{
        FileOutputStream fos = new FileOutputStream(zipFile);
        ZipOutputStream zos = new ZipOutputStream(fos);
        for(String file : this.fileList){
            ZipEntry ze= new ZipEntry(file);
            zos.putNextEntry(ze);
            FileInputStream in = new FileInputStream(SOURCE_FOLDER + File.separator + file);
            int len;
            while ((len = in.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            in.close();
        }
        zos.closeEntry();
        zos.close();
    }catch(IOException ex){
        LOGGER.error("Exception occurred while zipping file",ex);
    }
}

Upvotes: 3

Views: 17024

Answers (4)

Vasu
Vasu

Reputation: 22402

In order to avoid resource leaks, it is always best practice to close the resource objects (like your FileOutputStream, etc..) in the finally block. The reason is that finally block gets executed even upon exception and the resource will never get leaked or escaped.

The important thing in your code is that you are NOT closing the resources in the finally block i.e., they can escape & produce leaks.

Instead of you closing the resoruces in the finally block, try-with-resources is just a syntactic sugar to close any resource class (which implement AutoCloseable) objects (this is introduced in Java1.7)

You can apply try-with-resources concept as shown below for your code with inline comments:

public void archivingTheFile(String zipFile){
            byte[] buffer = new byte[1024];

            //wrap the resources inside try(....)
            try(FileOutputStream fos = 
                        new FileOutputStream(zipFile);
                    ZipOutputStream zos = new ZipOutputStream(fos);) {
                for(String file : this.fileList){
                    ZipEntry ze= new ZipEntry(file);
                    zos.putNextEntry(ze);

                    //wrap this resource as well inside try(....)
                    try(FileInputStream in = 
                      new FileInputStream(SOURCE_FOLDER + File.separator + file)){
                        int len;
                        while ((len = in.read(buffer)) > 0) {
                            zos.write(buffer, 0, len);
                        }
                    } catch(IOException ex) {
                         LOGGER.error("Exception occurred while zipping file",ex);
                    }
                }
            }catch(IOException ex){
                LOGGER.error("Exception occurred while zipping file",ex);
            }
        }

I suggest you look here for more details and understand this concept.

Upvotes: 5

NyxCode
NyxCode

Reputation: 728

Here you go.

public void archivingTheFile(String zipFile){
byte[] buffer = new byte[1024];
    try (FileOutputStream fos = new FileOutputStream(zipFile);
        ZipOutputStream zos = new ZipOutputStream(fos)) {
        for(String file : this.fileList){
            ZipEntry ze = new ZipEntry(file);
            zos.putNextEntry(ze);
            try (FileInputStream in = new FileInputStream(SOURCE_FOLDER + File.separator + file)) {
                int len;
                while ((len = in.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
            }
        }
        zos.closeEntry();
    } catch(IOException ex){
        LOGGER.error("Exception occurred while zipping file",ex);
    }
}

Upvotes: 0

M A
M A

Reputation: 72844

A side note: try-with-resources statements were introduced in Java 7.

The resources to be disposed of in this case are the FileOutputStream, the ZipOutputStream and the FileInputStream. Formally speaking, they can be used in try-with-resources because they implement AutoCloseable. So you can write the code as follows:

Java 7+

public void archivingTheFile(String zipFile){
    byte[] buffer = new byte[1024];
    try(FileOutputStream fos = new FileOutputStream(zipFile);
        ZipOutputStream zos = new ZipOutputStream(fos)) {
        for(String file : this.fileList){
            ZipEntry ze= new ZipEntry(file);
            zos.putNextEntry(ze);
            try(FileInputStream in = new FileInputStream(SOURCE_FOLDER + File.separator + file)) {
                int len;
                while ((len = in.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
            }
        }
        zos.closeEntry();

    }catch(IOException ex){
        LOGGER.error("Exception occurred while zipping file",ex);
    }
}

Notice that you don't need to call FileOutputStream.close() or FileInputStream.close().

Why is Sonar telling you to use these statements?

It's because they are the best way to deal with objects that represent resources such as IO streams while ensuring that they are closed at the end. Otherwise, resources may leak in your system. With Java 6 code, the alternative is to use try-catch-finally:

Java 6

FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
    fos = new FileOutputStream(zipFile);
    zos = new ZipOutputStream(fos)
    ...
} catch(IOException ex){
    LOGGER.error("Exception occurred while zipping file",ex);
} finally {
    if(fos != null) {
       fos.close();
    }
    if(zos != null) {
       zos.close();
    }
}

You can read about the try-with-resources statement from the Java tutorials: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html.

Upvotes: 2

JMax
JMax

Reputation: 1202

Additionally I increased the copy buffer. On file system operation the minimum buffer size should be 4094 as this is the block size on most OS/file-systems.

public void archivingTheFile(String zipFile) {
    byte[] buffer = new byte[4096];
    try (FileOutputStream fos = new FileOutputStream(zipFile); ZipOutputStream zos = new ZipOutputStream(fos)) {

        for (String file : this.fileList) {
            ZipEntry ze = new ZipEntry(file);
            zos.putNextEntry(ze);
            try (FileInputStream in = new FileInputStream(SOURCE_FOLDER + File.separator + file)) {
                int len;
                while ((len = in.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
            }
        }
        zos.closeEntry();
    } catch (IOException ex) {
        LOGGER.error("Exception occurred while zipping file", ex);
    }
}

Upvotes: 0

Related Questions