Jesse Ford
Jesse Ford

Reputation: 31

Copying Jar file without corruption

I need to copy a .jar file (which is a resource in my project) from a separate runnable jar to the startup folder in windows. Here's the code I have so far.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Installer {
    
    public static void main(String[] args) throws IOException
    {
        InputStream source = Installer.class.getResourceAsStream("prank.jar");
        
        byte[] buffer = new byte[source.available()];
        source.read(buffer);
        
        File targetFile = new File(System.getProperty("user.home") + File.separator + "AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\prank.jar");
        OutputStream outStream = new FileOutputStream(targetFile);
        outStream.write(buffer);
        
        outStream.close();
        
    }

}

My problem is that after the jar file is copied, it is corrupt (although the size of the original and the copy are the same.) Any thoughts on how to do this and have a runnable jar at the end of the process?

Upvotes: 2

Views: 500

Answers (2)

samabcde
samabcde

Reputation: 8114

Refer to InputStream#available does not work. The following line

byte[] buffer = new byte[source.available()];

is not correct, as available only return estimate of the size, the jar will be corrupted when estimate is different with actual. (Example from Java – Write an InputStream to a File) seems incorrect as I can't find any reference that guarantee correctness of available for FileInputStream.
Solution from How to convert InputStream to File in Java is more robust,

    private static void copyInputStreamToFile(InputStream inputStream, File file)
        throws IOException {

        try (FileOutputStream outputStream = new FileOutputStream(file)) {

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

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

            // commons-io
            //IOUtils.copy(inputStream, outputStream);

        }
    }

You can consider to use

  1. IOUtils#copy(InputStream, OutputStream)
  2. Files#copy(InputStream, Path, CopyOption...) suggested by Holger for jdk 1.7 or above

Upvotes: 1

Neeraj Benjwal
Neeraj Benjwal

Reputation: 1351

Try this -

    Path source = Paths.get("location1/abc.jar");
    Path destination = Paths.get("location2/abc.jar");
    try {
        Files.copy(source, destination);
    } catch(FileAlreadyExistsException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

Upvotes: 1

Related Questions