Hi guys.

I'm working on a christmas present for my dad, it's a program that installs 8 Black Keys songs on his computer. I'm having some trouble with it though. I can't figure out how to get the files out of the jar file. I used to access them with \\src\\package\\filename.fileending and had no problem but it's not working for some reason now. I'm using the java.nio package to copy the files, and this is my code. (I got the ExportResource method from this StackOverflow question)

The Window Class

package installer;

import javax.swing.*;

import java.awt.*;

@SuppressWarnings("serial")
public class InstallerWindow extends JFrame {

    JPanel panel;
    JTextField filePath;
    JLabel filePathValidator;
    JPanel panel1;
    JPanel panel2;
    JButton install;
    JButton next;
    CardLayout cl;
    JLabel label1 = new JLabel("Choose what folder to put the music in");

    public InstallerWindow(Engine engine){

        cl = new CardLayout();
        panel = new JPanel();
        panel.setLayout(cl);
        filePath = new JTextField("C:\\Users\\Aguilera\\Music");
        install = new JButton("Install Music");
        next = new JButton("Next");
        install.setActionCommand("install");
        next.setActionCommand("next");
        filePathValidator = new JLabel("Valid");
        panel1 = new JPanel();
        panel2 = new JPanel();

        panel1.setLayout(new BoxLayout(panel1, BoxLayout.PAGE_AXIS));
        panel1.add(new JLabel("Happy Birthday Pops!"));
        panel1.add(new JLabel("This program will install some Black Keys music."));
        panel1.add(next);

        panel2.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;
        panel2.add(label1 ,c);
        c.gridy = 1;
        c.ipadx = 70;
        panel2.add(filePath, c);
        c.gridx = 1;
        c.ipadx = 0;
        panel2.add(filePathValidator, c);
        c.gridy = 2;
        c.gridx = 0;
        panel2.add(install, c);

        panel.add(panel1, "InfoPanel");
        panel.add(panel2, "InstallPanel");

        next.addActionListener(engine);
        install.addActionListener(engine);

        this.setContentPane(panel);

    }

}

Logical Class

package installer;

import javax.swing.*;

import java.awt.event.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static java.nio.file.StandardCopyOption.*;

public class Engine implements ActionListener {

    InstallerWindow installer;

    public Engine(){

        installer = new InstallerWindow(this);
        installer.cl.first(installer.panel);
        installer.pack();
        installer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        installer.setLocation(300, 300);
        installer.setVisible(true);

    }

    public static void main(String args[]){

        new Engine();

    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if(e.getActionCommand().equals("next")){

            installer.cl.last(installer.panel);

        }else if(e.getActionCommand().equals("install")){

            installMusic();

        }else{

            System.out.println("There was a glitch. Oops");

        }

    }

    public void installMusic() {

        try{

            Path target = Paths.get(installer.filePath.getText());

            if(!Files.isWritable(target)){
                installer.filePathValidator.setText("Invalid");
                return;
            }

            installer.label1.setText("Installing file 1");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Fever.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 2");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Gold On The Ceiling.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 3");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Gotta Get Away.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 4");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Howlin For You.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 5");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Little Black Submarines.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 6");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Lonely Boy.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 7");
            Files.copy(Paths.get(ExportResource("/[Black Keys] The Baddest Man Alive.mp3")), target, REPLACE_EXISTING);
            installer.label1.setText("Installing file 8");
            Files.copy(Paths.get(ExportResource("/[Black Keys] Lighten Up.mp3")), target, REPLACE_EXISTING);

            installer.install.setText("Done");
            installer.install.setEnabled(false);

        }catch(Exception ioe){
            installer.install.setText("Try Again?");
            installer.label1.setText(ioe.getMessage());
            System.out.println(ioe);
        }

    }

    static public String ExportResource(String resourceName) throws Exception {
        InputStream stream = null;
        OutputStream resStreamOut = null;
        String jarFolder;
        try {
            stream = Engine.class.getResourceAsStream(resourceName);
            if(stream == null) {
                throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
            }

            int readBytes;
            byte[] buffer = new byte[4096];
            jarFolder = new File(Engine.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
            resStreamOut = new FileOutputStream(jarFolder + resourceName);
            while ((readBytes = stream.read(buffer)) > 0) {
                resStreamOut.write(buffer, 0, readBytes);
            }
        } catch (Exception ex) {
            System.out.println(ex);
            throw ex;
        } finally {
            stream.close();
            resStreamOut.close();
        }

        return jarFolder + resourceName;
    }

}

The latest error is that it's copying just the first song to the wrong location (the location of the program). The program is on a USB drive.

Dani AI

Generated

Short diagnosis and a quick fix for

Two things are tripping this up. First: calling Files.copy(sourcePath, targetPath, ...) with targetPath set to the destination directory is wrong—Files.copy(Path,Path,...) expects a target file (or you must explicitly resolve the filename into the directory). Second: when you wrap a JAR with Launch4j the code location you used to compute jarFolder will typically point at the launcher/exe location, so any temporary files your ExportResource writes will end up next to the EXE (your USB) rather than in the user folder. (docs.oracle.com)

What to change (small, safe edits)

Avoid extracting to the exe folder and avoid using Paths.get(exportedString) as the intermediate step. Read the resource stream directly from the classpath and copy it into the destination filename. In other words: open the resource with getResourceAsStream(...), compute the output filename under the chosen directory (eg. target.resolve("song.mp3")) and use the InputStream-based Files.copy(...) so Java writes the file for you (use try-with-resources and REPLACE_EXISTING). This removes the need to write temp files next to the EXE and prevents the directory-vs-file target mistake. The Class.getResourceAsStream API and the Files.copy(InputStream, Path, ...) overload are the right building blocks here. (docs.oracle.com)

Extra troubleshooting tips

  • Make sure the resource paths you call are actually packaged into the JAR (check with jar tf your.jar or your IDE resource settings). getResourceAsStream treats a leading / as an absolute classpath path. (docs.oracle.com)
  • If the destination directory may not exist, call Files.createDirectories(target) first. Files.isWritable(path) returns false if the path does not exist, so don’t rely on it alone to validate a target. Also log full stack traces while testing so you see exactly which call fails. (docs.oracle.com)
  • If you really need to run elevated to write into protected locations, configure the launcher/manifest to request elevation (or run the installer elevated) rather than writing next to the EXE; Launch4j/config can be adjusted for that. (launch4j.sourceforge.net)

If needed, paste the minimal snippet you switch to (resource name and a safe target.resolve(...)) and the exact exception text and the contents of the wrapped JAR (via jar tf) and it’s straightforward to point out the final missing bit.

Oops I forgot to mention I'm using the wrapper to get admin priviliges to copy the files to whatever the desired location is.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.