0

As part of my project auto-update functionality, my program downloads a zip file from a web server and then unzip it in place before relaunching the app (here below is the code logic). The zip file is supposed to be deleted after the files have been updated and before the main app is launched.

The download and files update is working well but the issue I am facing is that the line Files.delete(file.toPath()); throws an error of type java.nio.file.FileSystemException with the description The process cannot access the file because it is being used by another process. It seems like the call to zis.close() is not effectively releasing the handle on update.zip. Any indication on how I could fix this?

public static void main(String[] args) {

    String updateFileName = "update.zip";
    boolean updateSuccess=true;
    File file = new File(updateFileName);
    if (file.exists()) {
        String dir = file.getAbsolutePath();
        dir = dir.substring(0, dir.length() - 10);
        try {
            update(updateFileName, dir);
        }
        catch (Exception e) {
            updateSuccess = false;
            System.err.print("update failed !");
            e.printStackTrace();
        }
        if (updateSuccess) {
            try {
                System.err.print("Trying to delete  " + file.getAbsolutePath());
                Files.delete(Path.of(file.getAbsolutePath()));
            } catch (IOException e) {
                System.err.print("zip file could not be deleted after update !: " + e );
            }
        }
    }
    HO.main(args);
}

private static void update(String zipFile, String _destDir) throws IOException {
    int len;
    Pattern pattern;
    String fileName;
    byte[] buffer = new byte[1024];
    File destDir = new File(_destDir);
    try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
        ZipEntry zipEntry = zis.getNextEntry();
        while (zipEntry != null) {
            File destFile = new File(destDir, fileName);
            File parentDirectory = destFile.getParentFile();
            if (!parentDirectory.exists()) parentDirectory.mkdirs();
            else {
                if (destFile.exists()) destFile.delete();
            }
            FileOutputStream fos = new FileOutputStream(destFile, false);
            while ((len = zis.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            zipEntry = zis.getNextEntry();
        }
        zis.closeEntry();
    }
}
akasolace
  • 572
  • 1
  • 5
  • 17
  • 1
    Why you create a zip files and delete it after creation? – Jens Aug 20 '20 at 07:55
  • 1
    Have you tried using "try-with-resources" instead of manually closing the input stream? – Smutje Aug 20 '20 at 07:57
  • You should look at that request : https://stackoverflow.com/questions/40779633/java-the-process-cannot-access-the-file-because-it-is-being-used-by-another-pr – 0009laH Aug 20 '20 at 07:59
  • @Jens I do not create the zip file, it is downloaded from the webserver. – akasolace Aug 20 '20 at 08:46
  • 1
    Why do you save the downloaded ZIP file? If you wrap the download stream in a `ZipInputStream` and decompress it, you don't need to delete any files. –  Aug 20 '20 at 08:47
  • `if (destFile.exists()) destFile.delete()`: you don't need this. `new FileOutputStream()` already does it. You're just doing it twice. Don't keep a dog and bark yourself. – user207421 Aug 20 '20 at 09:55
  • @MarquisofLorne thank you I will correct this – akasolace Aug 20 '20 at 10:58
  • Side note: Please consider to use the Zip File System Provider for the Java NIO.2 File API instead of using the low-level Zip API. See https://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html and https://docs.oracle.com/en/java/javase/11/docs/api/jdk.zipfs/module-summary.html – Puce Aug 20 '20 at 13:12
  • @Smutje I tried and updated the code accordingly but this does not fix my issue – akasolace Aug 20 '20 at 14:19
  • @saka1029 I prefer not to change to much of the program architecture. I imagine it should be possible to delete that zip file after reading it ... – akasolace Aug 20 '20 at 14:20
  • @Puce thanks for the advice, I will try to use ZipFile, see if it fixes my issue ... – akasolace Aug 20 '20 at 14:38
  • There is a compilation error `The local variable fileName may not have been initialized` at the line `File destFile = new File(destDir, fileName);` Then add `fileName = zipEntry.getName();` before that line and your code will work. –  Aug 20 '20 at 19:41

1 Answers1

0

you should use 'try with resource' for stream if it implements closable.. check below https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

      if (file.exists()) {
            try (ZipInputStream zis = new ZipInputStream(new FileInputStream(updateFileName))) {
                zis.closeEntry();
            }
            Files.delete(Path.of(file.getAbsolutePath()));
            myApp.main(args);
        }
Rahul Sawant
  • 1,223
  • 9
  • 12