1

I am currently making a game which have levels which are pre-made and i currently store them in resources. I want a solution to how i can extract a folder out of a jar in production and development environment.

I have tried copying the folder by using the given method below and pass the src as File defaultWorld = new File(GameData.class.getClassLoader().getResource("worlds/").getFile()); and destination as private static File worldsDir = new File("run/worlds");

public static void copyFolder(File src, File dest) {
    try {
        if (src.isDirectory()) {
            if (!dest.exists()) {
                dest.mkdir();
            }
            String[] files = src.list();

            for (String file : files) {
                copyFolder(new File(src, file), new File(dest, file));
            }
        } else {
            try (InputStream in = new FileInputStream(src)) {
                try (OutputStream out = new FileOutputStream(dest)) {
                    byte[] buffer = new byte[1024];
                    int length;
                    //copy the file content in bytes
                    while ((length = in.read(buffer)) > 0) {
                        out.write(buffer, 0, length);
                    }
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

I expected the above method to work on both dev and production env but it throws FileNotFoundException when opening file output stream.

Daniel Campos Olivares
  • 2,262
  • 1
  • 10
  • 17

1 Answers1

1

You cannot list resources in a jar.

Any workarounds you’re thinking of, are unreliable.

  • Never call the getFile() method of URL. It does not return a valid file name; it just returns the path and query portions of the URL, with any percent-escapes intact. Furthermore, jar entries are not file: URLs, so a resource path can never be a valid file name when it refers to a jar entry.
  • The only way to list things in a jar file is by iterating through all jar entries, but you aren’t even guaranteed to have access to your jar, because ClassLoaders are not guaranteed to be URLClassLoaders, and in general are not guaranteed to use jar: URLs.
  • You can’t even rely on MyApplication.class.getProtectionDomain().getCodeSource(), because getCodeSource() can return null.

If you want to copy multiple files from your jar, here are some reliable ways to do it:

  • Hard code the list of resources you plan to copy. It’s your application, so you know what files you’re putting in the jar.
  • Keep a single text file in your jar which contains a list of resource paths to copy.
  • Store your resources in a single zip archive which is embedded in your jar, and extract it yourself with a ZipInputStream which wraps MyApplication.class.getResourceAsStream.
VGR
  • 40,506
  • 4
  • 48
  • 63