java 从Jar文件中的资源复制/提取目录

efzxgjgh  于 2023-01-29  发布在  Java
关注(0)|答案(3)|浏览(334)

我正在写一个应用程序,需要从它的资源目录中复制一些静态资产,目录结构是这样的;

java/
resources/
    assets/
        file1.txt
        file2.txt
        subdir/
            file3.txt

我想把assets目录(递归)复制到文件系统的一个位置,如果我使用IOUtils.copy(InputStream in, OutputStream out),那么我会得到一个空指针异常。

InputStream in = getClass().getResourceAsStream("/assets");
OutputStream out = new FileOutputStream(new File("/path/to/write/to"));
IOUtils.copy(in, out);

Exception in thread "main" java.lang.NullPointerException
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2146)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2102)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2123)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2078)

但是,如果我更改输入和输出流,使它们成为文件而不是目录,那么它复制得很好。
是否有一种方法可以递归地将属于jar的目录复制到文件系统中?

rjjhvcjd

rjjhvcjd1#

把你所有的资产文件放到一个zip文件中,就像Reddymails链接到的问题中提到的那样,是一个很好的方法。
如果您希望将资产文件作为单独的条目保存在.jar中,问题是您将没有目录可供列出:

  • .jar或zip文件中的目录条目只是一个名称;没有办法“列出”它。
  • .jar文件并不总是可获得的,因为ProtectionDomain.getCodeSource()允许返回null。
  • 有一些复杂的ClassLoader可以从目录或.jar文件以外的源文件中读取。

你可以让你的构建过程在打包它们之前在一个文本文件中列出这些条目(因为你毕竟知道它们是什么),并把这个文本文件包含在你的. jar中,然后在运行时复制它们就像从这个文件中阅读一样容易:

Path assetDir = /* ... */;

try (BufferedReader listFile = new BufferedReader(
        new InputStreamReader(
            getClass().getResourceAsStream("assets-list.txt"),
            StandardCharsets.UTF_8))) {

    String assetResource;
    while ((assetResource = listFile.readLine()) != null) {
        Path assetFile = assetDir.resolve(assetResource);
        Files.createDirectories(assetFile.getParent());
        try (InputStream asset = getClass().getResourceAsStream(assetResource)) {
            Files.copy(asset, assetFile);
        }
    }
}
ruyhziif

ruyhziif2#

如果有人还在寻找这一点,我刚刚分享了一个类,它正是这样做的:将资源目录复制到文件系统中的目标位置。可在以下位置找到:https://stackoverflow.com/a/58318009/738968

nle07wnf

nle07wnf3#

如果您对从JAR文件内的资源复制文件感兴趣
使用(apache commons-io)依赖项可以非常容易

import org.apache.commons.io.FileUtils

public void copyResourceFileInsideJarToPath(String resourceName, Path toPath) throws IOException {
    URL fromURL = getClass().getClassLoader().getResource(resourceName);
    LOGGER.info("fromURL: {}", fromURL);
    LOGGER.info("toPath: {}", toPath.toAbsolutePath());

    Files.deleteIfExists(toPath);
    FileUtils.copyURLToFile(fromURL, toPath.toFile());
}

相关maven依赖性:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

相关问题