Pau Marin
Pau Marin

Reputation: 36

.zip file isn't deleted but neither throw any exception

I've created an app with utilities I usually use on my pc (like sending shutdown to cmd.exe) and as some friends asked me to give it to them I was trying to add an update system that checks for updates on a server to make it easier that their version is always updated.

The thing is that I've been over the net searching any solution but all of them just tell to use .close() and my file has it right after stop needing it. When I run it everything works fine and there are no exceptions thrown, so I just dunno what can be wrong.

Whole class:

public class Main_Gui extends JFrame {

        private Thread worker;
        private final String root = "update/";

        private JTextArea outText;
        private JButton cancel;
        private JButton launch;
        private JScrollPane sp;
        private JPanel pan1;
        private JPanel pan2;

        private String zipFile = "Actualización.zip";
        private String path = "http://ritsu.hol.es/url.html";
        private String TITLE = "RitsUtilities | Actualizador";

        public Main_Gui() {
            initComponents();
            outText.setText("Conectando con el servidor...");
            download();
        }

        private void initComponents() {

            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            setTitle(TITLE);
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

            pan1 = new JPanel();
            pan1.setLayout(new BorderLayout());

            pan2 = new JPanel();
            pan2.setLayout(new FlowLayout());

            outText = new JTextArea();
            sp = new JScrollPane();
            sp.setViewportView(outText);

            launch = new JButton("Ejecutar RitsUtilities");
            launch.setEnabled(false);
            launch.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    String[] run = { "java", "-jar", "RitsUtilities.jar" };
                    try {
                        Runtime.getRuntime().exec(run);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                    System.exit(0);
                    launch();
                }
            });
            pan2.add(launch);

            cancel = new JButton("Salir");
            cancel.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });
            pan2.add(cancel);
            pan1.add(sp, BorderLayout.CENTER);
            pan1.add(pan2, BorderLayout.SOUTH);

            add(pan1);
            pack();
            setSize(500, 400);
            setLocationRelativeTo(null);

        }

        private void download() {

            worker = new Thread(new Runnable() {

                public void run() {
                    try {
                        downloadFile(getDownloadLinkFromHost());
                        unzip();
                        copyFiles(new File(root), new File("").getAbsolutePath());
                        cleanup();
                        launch.setEnabled(true);
                        outText.setText(outText.getText() + "\n¡Actualización completada con éxito!");
                    } catch (Exception e) {
                        e.printStackTrace();
                        JOptionPane.showMessageDialog(null, "Ha ocurrido un error al descargar y descomprimir la actualización.", "Error 1", JOptionPane.WARNING_MESSAGE);
                    }
                }
            });
            worker.start();
        }

        private void launch() {
            String[] run = { "java", "-jar", "update app.jar" };
            try {
                Runtime.getRuntime().exec(run);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            System.exit(0);
        }

        private void cleanup() {
            outText.setText(outText.getText() + "\nLimpiando archivos temporales...");
            remove(new File(root));
            new File(root).delete();
        }

        private void remove(File f) {
            File[] files = f.listFiles();
            for (File ff : files) {
                if (ff.isDirectory()) {
                    remove(ff);
                    ff.delete();
                } else {
                    ff.delete();
                }
            }

        }

        private void copyFiles(File f, String dir) throws IOException {
            File[] files = f.listFiles();
            for (File ff : files) {
                if (ff.isDirectory()) {
                    new File(dir + "/" + ff.getName()).mkdir();
                    copyFiles(ff, dir + "/" + ff.getName());
                } else {
                    copy(ff.getAbsolutePath(), dir + "/" + ff.getName());
                }

            }
        }

        public void copy(String srFile, String dtFile) throws FileNotFoundException, IOException {

            File f1 = new File(srFile);
            File f2 = new File(dtFile);

            InputStream in = new FileInputStream(f1);
            OutputStream out = new FileOutputStream(f2);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();
        }

        private void unzip() throws IOException {
            int BUFFER = 2048;
            BufferedOutputStream dest = null;
            BufferedInputStream is = null;
            ZipEntry entry;
            ZipFile zipfile = new ZipFile(zipFile);
            Enumeration e = zipfile.entries();
            (new File(root)).mkdir();
            while (e.hasMoreElements()) {
                entry = (ZipEntry) e.nextElement();
                outText.setText(outText.getText() + "\nExtrayendo: " + entry);
                if (entry.isDirectory())
                    (new File(root + entry.getName())).mkdir();
                else {
                    (new File(root + entry.getName())).createNewFile();
                    is = new BufferedInputStream(zipfile.getInputStream(entry));
                    int count;
                    byte data[] = new byte[BUFFER];
                    FileOutputStream fos = new FileOutputStream(root + entry.getName());
                    dest = new BufferedOutputStream(fos, BUFFER);
                    while ((count = is.read(data, 0, BUFFER)) != -1) {
                        dest.write(data, 0, count);
                    }
                    dest.flush();
                    dest.close();
                    is.close();
                }
            }

        }

        private void downloadFile(String link) throws MalformedURLException, IOException {
            URL url = new URL(link);
            URLConnection conn = url.openConnection();
            InputStream is = conn.getInputStream();
            long max = conn.getContentLength();
            outText.setText(outText.getText() + "\n" + "Descargando archivo...\nTamaño de la actualización(comprimida): " + max + " Bytes");
            BufferedOutputStream fOut = new BufferedOutputStream(new FileOutputStream(new File(zipFile)));
            byte[] buffer = new byte[32 * 1024];
            int bytesRead = 0;
            int in = 0;
            while ((bytesRead = is.read(buffer)) != -1) {
                in += bytesRead;
                fOut.write(buffer, 0, bytesRead);
            }
            fOut.flush();
            fOut.close();

            is.close();
            outText.setText(outText.getText() + "\n¡Descarga completada!");

        }

        private String getDownloadLinkFromHost() throws MalformedURLException, IOException {

            URL url = new URL(path);
            InputStream html = null;
            html = url.openStream();
            int c = 0;
            StringBuilder buffer = new StringBuilder("");

            while (c != -1) {
                c = html.read();
                buffer.append((char) c);
            }
            return buffer.substring(buffer.indexOf("[url]") + 5, buffer.indexOf("[/url]"));
        }

        public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {

                public void run() {
                    new Main_Gui().setVisible(true);
                }
            });
        }

    }

EDIT: changed private String zipFile = "Actualización.zip"; to private String zipFile = "Update.zip"; but still just deleting temp files/directories but not that "Update.zip" folder that the app downloads.

Upvotes: 0

Views: 130

Answers (3)

Pau Marin
Pau Marin

Reputation: 36

Finally it's working, just added a forced delete on run() inside download() so now my code looks like

public void run() {
                try {
                    downloadFile(getDownloadLinkFromHost());
                    unzip();
                    copyFiles(new File(root), new File("").getAbsolutePath());
                    cleanup();
                    launch.setEnabled(true);
                +   System.gc();
                +   File tmpf = new File(zipFile);
                +   tmpf.deleteOnExit();
                    outText.setText(outText.getText() + "\n¡Actualización completada con éxito!");
                } catch (Exception e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(null, "Ha ocurrido un error al descargar y descomprimir la actualización.", "Error 1", JOptionPane.WARNING_MESSAGE);
                }
            }

I'm pretty sure that there are way better ways to do this, but that one seems to work for me.

Thanks to everyone that answered and tried to help me. =D

Upvotes: 1

jotadepicas
jotadepicas

Reputation: 2493

I would suggest improving your remove(File f) method. Add some checks for the Boolean return value of ff.delete(), that will tell you if the file is actually being deleted or not.

Also, you could add some logs into that method, so you could debug what is actually doing, perhaps it's not seeing the files or something.

One last comment. You should make your code more modular. Create more abstractions and give each of them a simple task. That is the essence of Object Oriented Design. Then, you can program some JUnit tests for each object, and you can run the tests every time you make a change. I reccomend you give a look to this article on Cohesion

Upvotes: 0

Keppil
Keppil

Reputation: 46239

The File#delete() method you are using doesn't throw an error if the file can't be deleted, it returns false. This is documented in the Javadoc, together with an alternative solution (emphasize mine):

Deletes the file or directory denoted by this abstract pathname. If this pathname denotes a directory, then the directory must be empty in order to be deleted.
Note that the Files class defines the delete method to throw an IOException when a file cannot be deleted. This is useful for error reporting and to diagnose why a file cannot be deleted.

Upvotes: 1

Related Questions