Higeath
Higeath

Reputation: 561

Copying images from JAR file to a folder outside

My file structure:

This is how it looks using netbeans project:

-src
    -images
        -*.jpg
    -stock
        -*.java
-images (exact copy of -images) 

and here is my jar

-jar
    -images
        -*.jpg
    -stock
        -*.java
-images (folder is created but files don't get copied) 

My files imagesCopy is the one that I create and ImagesOrg is the one inside .jar / src

 File imagesCopy = new File("images");
 File imagesOrg = new File(URLDecoder.decode(getClass().getResource("/images").getPath()));

 if (!imagesCopy.exists()) {
            imagesCopy.mkdir();
                for(final File child : imagesOrg.listFiles()) {
                    try{
                        Files.copy(child.toPath(), Paths.get(imagesCopy.getAbsolutePath()+"/"+child.getName()), REPLACE_EXISTING);
                    }catch(Exception e){
                        System.out.println(e);
                    }
                }
        }

The problem definitely lies with:

File imagesOrg = new File(URLDecoder.decode(getClass().getResource("/images").getPath()));

When compiling it it gives me, which is the proper directory

D:\Code\build\classes\images 

which is the right directory, but when using this program from jar file I get:

D:\Code\dist\file:\D:\Code\dist\egz.jar!\images

and I assume that it should just be:

D:\Code\dist\egz.jar!\images

without that first part

Upvotes: 3

Views: 1197

Answers (2)

ipsi
ipsi

Reputation: 2070

Probably the simplest way to do it is like this:

public static void main(String[] args) throws URISyntaxException, IOException {
    File imagesCopy = new File("C:\\Users\\<YOURNAMEHERE>\\images");

    URI uri = ImageCopy.class.getResource("/images").toURI();
    if (!uri.toString().startsWith("file:")) {
        Map<String, String> env = new HashMap<>();
        env.put("create", "true");
        FileSystems.newFileSystem(uri, env);
    }
    Path imagesOrg = Paths.get(uri);
    System.out.println(imagesOrg);

    if (!imagesCopy.exists()) {
        imagesCopy.mkdir();
        try(DirectoryStream<Path> paths = Files.newDirectoryStream(imagesOrg)) {
            for (final Path child : paths) {
                System.out.println(child);
                try {
                    String targetPath = imagesCopy.getAbsolutePath() + File.separator + child.getFileName().toString();
                    System.out.println(targetPath);
                    Files.copy(child, Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

It's not super-pretty, but it works. Might need to fiddle with the code if you have nested directories.

Note that you must create the FileSystem before accessing it (as per the Oracle Docs). I don't know why this is required, but there we go.

I've tested this and it will copy files from inside your JAR to wherever you would like.

Upvotes: 3

Jorge Campos
Jorge Campos

Reputation: 23361

Here is a simple code to do it. You can adapt as you need.

package br.com.jjcampos.main;

//imports here

public class CopyImage {

    private static ClassLoader loader = CopyImage.class.getClassLoader();

    public static void main(String[] args) throws IOException {
        InputStream stream = loader.getResourceAsStream("br/com/jjcampos/images/test.jpg");

        OutputStream outputStream = 
                new FileOutputStream(new File("c:/temp/newImage.jpg"));

        int read = 0;
        byte[] bytes = new byte[1024];

        while ((read = stream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, read);
        }
        outputStream.close();
    }
}

Understand that you can't copy a source from a stream (your jar) as a list of files. Unless you want to unpack it first. My suggestion is you to add a txt file with the list of your images then you read this file and use suggested code to copy each one.

Something like this:

public class CopyImage {

    private static ClassLoader loader = CopyImage.class.getClassLoader();

    public static void main(String[] args) throws IOException {
        copyImages("c:/temp/");
    }


    public static void copyImages(String pathDestiny) throws IOException{
        InputStream listOfFiles = loader
           .getResourceAsStream("br/com/jjcampos/images/listImages.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(listOfFiles));
        String line;
        while ( (line = reader.readLine())!=null ){
            InputStream stream = loader.getResourceAsStream("br/com/jjcampos/images/" 
                                                               + line);
            OutputStream outputStream = 
                    new FileOutputStream(new File(pathDestiny + line));
            int read = 0;
            byte[] bytes = new byte[1024];
            while ((read = stream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
            outputStream.close();
        }
    }
}

And your listImages.txt with

test.jpg

And you should decide if you put the full path on the text file or not to use in your code.

Upvotes: 1

Related Questions