1

I've created a pretty simple Java GUI to browse/load a zip file on Windows platform to begin unzipping and then do some file checking.

Everything works fine except that I have to close the GUI window in order to delete the zip file that has been opened in the GUI.In my finally block of the unzipping method, I've tried adding the following:

public static String unZip(String path)
{
    int count = -1;
    String savepath = "";
    File file = null;
    InputStream is = null;
    FileOutputStream fos = null;
    BufferedOutputStream bos = null;
    savepath = path.substring(0, path.lastIndexOf("\\")) + File.separator; //File saving directory
    new File(savepath).mkdir(); //create the saving directory
    ZipFile zipFile = null;
    String topLevelDirName="";
    try
    {
        zipFile = new ZipFile(path,Charset.forName("gbk")); //Encoding
        Enumeration<?> entries = zipFile.entries();
        int levelCount=0;
        while(entries.hasMoreElements())
        {
            byte buf[] = new byte[buffer];
            ZipEntry entry = (ZipEntry)entries.nextElement();
            String filename = entry.getName();
            boolean ismkdir = false;
            if(filename.lastIndexOf("/") != -1){ //To check if there is a directory
                ismkdir = true;
            }
            filename = savepath + filename;
            if(entry.isDirectory()){ //If it is a directory
                levelCount++;
                file = new File(filename);
                file.mkdirs();
                if(levelCount==1)
                    topLevelDirName = filename;
                continue;
            }

            file = new File(filename);
            if(!file.exists()){
                if(ismkdir){
                    new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs();
                }
            }


            file.createNewFile(); //Create the file
            is = zipFile.getInputStream(entry);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos, buffer);
            while((count = is.read(buf)) > -1)
            {
                bos.write(buf, 0, count);
            }
            bos.flush();
            bos.close();
            fos.close();
            is.close();
        }
        zipFile.close();
    }catch(IOException ioe){
        ioe.printStackTrace();
    }finally{
        try{
            if(bos != null){
                bos.close();
            }
            if(fos != null) {
                fos.close();
            }
            if(is != null){
                is.close();
            }
            if(zipFile != null){
                zipFile.close();
            }

        }catch(Exception e) {
            e.printStackTrace();
        }
        return topLevelDirName;
    }
}

However, I am still not able to delete the zip unless explicitly close the GUI.

Wonder if there is anything to do with the Windows file handle?Thanks in advance.

Kevin
  • 6,711
  • 16
  • 60
  • 107

1 Answers1

1

Java 8 introduced the try-with-resources Statement to make this kind of situation simpler and cleaner.

One of the issues you have is, if any one of the attempts to close the many resources you have open fails, then none of the others will be closed

public static String unZip(String path) throws IOException {
    int count = -1;

    File sourceFile = new File(path);
    String name = sourceFile.getName();
    name = name.substring(0, name.lastIndexOf(".zip"));
    File sourcePath = new File(sourceFile.getParent(), name);

    System.out.println("SavePath = " + sourcePath);
    if (!sourcePath.exists() && !sourcePath.mkdirs()) {
        throw new IOException("Could not create directory " + sourcePath);
    }
    String topLevelDirName = "";
    try (ZipFile zipFile = new ZipFile(sourceFile)) {
        Enumeration<?> entries = zipFile.entries();
        int levelCount = 0;
        byte buf[] = new byte[1024];
        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String filename = entry.getName();
            File file = new File(sourcePath, filename);
            if (entry.isDirectory()) { //If it is a directory
                levelCount++;
                System.out.println("Make directory " + file);
                if (!file.exists() && !file.mkdirs()) {
                    throw new IOException("Could not create directory " + filename);
                }
            } else {
                System.out.println("Extract to " + file);
                try (InputStream is = zipFile.getInputStream(entry);
                                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
                    while ((count = is.read(buf)) > -1) {
                        bos.write(buf, 0, count);
                    }
                }
            }
        }
    }
    return topLevelDirName;
}

I've update the code slightly to try and make it a little cleaner and simpler and to take advantage of the available APIs

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • thanks,I've tried your code but it seems still doesn't allow me delete the zip file. Maybe I am missing something? – Kevin Sep 10 '18 at 08:33
  • I don't know, since this all the code you've provided. This example works fine for me, maybe something else is holding the file open? Maybe try restarting the PC – MadProgrammer Sep 10 '18 at 08:34
  • great,actually another service is holding a reference to the zipFile and did not close. Now it works thanks! – Kevin Sep 10 '18 at 08:36