如何将jar中的文件复制到jar外?

jtl*_*999 42 java copy jar file working-directory

我想从jar中复制一个文件.我要复制的文件将被复制到工作目录之外.我做了一些测试,我尝试的所有方法都以0字节文件结束.

编辑:我希望通过程序复制文件,而不是手动.

Ord*_*iel 52

首先,我想说之前发布的一些答案是完全正确的,但我想给我的,因为有时我们不能在GPL下使用开源库,或者因为我们懒得下载jar XD或什么你的理由是一个独立的解决方案.

下面的函数复制Jar文件旁边的资源:

  /**
     * Export a resource embedded into a Jar file to the local file path.
     *
     * @param resourceName ie.: "/SmartLibrary.dll"
     * @return The path to the exported resource
     * @throws Exception
     */
    static public String ExportResource(String resourceName) throws Exception {
        InputStream stream = null;
        OutputStream resStreamOut = null;
        String jarFolder;
        try {
            stream = ExecutingClass.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
            if(stream == null) {
                throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
            }

            int readBytes;
            byte[] buffer = new byte[4096];
            jarFolder = new File(ExecutingClass.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) {
            throw ex;
        } finally {
            stream.close();
            resStreamOut.close();
        }

        return jarFolder + resourceName;
    }
Run Code Online (Sandbox Code Playgroud)

只需将ExecutingClass更改为您的类的名称,并将其命名为:

String fullPath = ExportResource("/myresource.ext");
Run Code Online (Sandbox Code Playgroud)

编辑Java 7+(为方便起见)

正如GOXR3PLUS所回答并由安迪·托马斯注意到的,您可以通过以下方式实现此目的:

Files.copy( InputStream in, Path target, CopyOption... options)
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅GOXR3PLUS答案

  • 在Java 7+中,一些代码可以用对`Files.copy(InputStream in,Path target,CopyOption ... options)`的简单调用来替换,如下面的最新答案所述. (2认同)

Rya*_*art 34

鉴于您对0字节文件的评论,我不得不假设您正在尝试以编程方式执行此操作,并且,鉴于您的标记,您正在使用Java进行此操作.如果这是真的,那么只需使用Class.getResource()来获取指向JAR中文件的URL,然后使用Apache Commons IO FileUtils.copyURLToFile()将其复制到文件系统.例如:

URL inputUrl = getClass().getResource("/absolute/path/of/source/in/jar/file");
File dest = new File("/path/to/destination/file");
FileUtils.copyURLToFile(inputUrl, dest);
Run Code Online (Sandbox Code Playgroud)

最有可能的是,您现在拥有的任何代码的问题是您(正确地)使用缓冲的输出流来写入文件但是(错误地)无法关闭它.

哦,你应该修改你的问题,以澄清究竟如何要做到这一点(编程,不是语言,...)


Luk*_*ino 12

Java 8(实际上是自1.7以来的FileSystem)附带了一些很酷的新类/方法来处理这个问题.有人已经提到JAR基本上是ZIP文件,你可以使用

final URI jarFileUril = URI.create("jar:file:" + file.toURI().getPath());
final FileSystem fs = FileSystems.newFileSystem(jarFileUri, env);
Run Code Online (Sandbox Code Playgroud)

(见Zip文件)

然后你可以使用一种方便的方法,如:

fs.getPath("filename");
Run Code Online (Sandbox Code Playgroud)

然后你可以使用Files类

try (final Stream<Path> sources = Files.walk(from)) {
     sources.forEach(src -> {
         final Path dest = to.resolve(from.relativize(src).toString());
         try {
            if (Files.isDirectory(from)) {
               if (Files.notExists(to)) {
                   log.trace("Creating directory {}", to);
                   Files.createDirectories(to);
               }
            } else {
                log.trace("Extracting file {} to {}", from, to);
                Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
            }
       } catch (IOException e) {
           throw new RuntimeException("Failed to unzip file.", e);
       }
     });
}
Run Code Online (Sandbox Code Playgroud)

注意:我尝试解压缩JAR文件以进行测试


GOX*_*LUS 11

使用Java 7+更快的方式,以及获取当前目录的代码:

   /**
     * Copy a file from source to destination.
     *
     * @param source
     *        the source
     * @param destination
     *        the destination
     * @return True if succeeded , False if not
     */
    public static boolean copy(InputStream source , String destination) {
        boolean succeess = true;

        System.out.println("Copying ->" + source + "\n\tto ->" + destination);

        try {
            Files.copy(source, Paths.get(destination), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException ex) {
            logger.log(Level.WARNING, "", ex);
            succeess = false;
        }

        return succeess;

    }
Run Code Online (Sandbox Code Playgroud)

测试它(icon.png是应用程序包图像中的图像):

copy(getClass().getResourceAsStream("/image/icon.png"),getBasePathForClass(Main.class)+"icon.png");
Run Code Online (Sandbox Code Playgroud)

关于代码行(getBasePathForClass(Main.class)): - >检查我在这里添加的答案:) - > 用Java获取当前工作目录


zor*_*ran 5

稳健的解决方案:

public static void copyResource(String res, String dest, Class c) throws IOException {
    InputStream src = c.getResourceAsStream(res);
    Files.copy(src, Paths.get(dest), StandardCopyOption.REPLACE_EXISTING);
}
Run Code Online (Sandbox Code Playgroud)

你可以这样使用它:

File tempFileGdalZip = File.createTempFile("temp_gdal", ".zip");
copyResource("/gdal.zip", tempFileGdalZip.getAbsolutePath(), this.getClass());
Run Code Online (Sandbox Code Playgroud)