复制Jar文件而不损坏

问题描述

我需要将一个.jar文件(这是我的项目中的资源)从一个单独的可运行jar中复制到Windows中的启动文件夹中。这是我到目前为止的代码

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();
        
    }

}

我的问题是,将jar文件复制后,它已损坏(尽管原始文件和副本的大小相同。)有关如何执行此操作的任何想法,并在过程结束时拥有可运行的jar ?

解决方法

尝试一下-

    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();
    }
,

请参阅InputStream#available does not work。 下一行

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

是不正确的,因为available仅返回大小的 estimate ,当 estimate 与实际值不同时,jar将损坏。 (来自Java – Write an InputStream to a File的示例)似乎不正确,因为我找不到任何能够保证availableFileInputStream正确的引用。
How to convert InputStream to File in Java的解决方案更可靠,

    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,read);
            }

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

        }
    }

您可以考虑使用

  1. IOUtils#copy(InputStream,OutputStream)
  2. Holger 为jdk 1.7或更高版本建议的
  3. Files#copy(InputStream,Path,CopyOption...)
,

您应该对资源使用try来关闭流,并且NIO Files.copy会为您处理InputStream:

public class Installer {
    
    public static void main(String[] args) throws IOException {
        Path targetFile = Path.of(System.getProperty("user.home"),"AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\prank.jar");

        try (InputStream source = Installer.class.getResourceAsStream("prank.jar")) {
            Files.copy(source,targetFile);
        }
    }
}