簡體   English   中英

從 Jar 文件中的資源復制/提取目錄

[英]Copy/extract directory from resources inside Jar file

我正在編寫一個需要從其資源目錄復制一些 static 資產的應用程序。 目錄結構是這樣的;

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

我想將資產目錄(遞歸地)復制到文件系統上的某個位置。 如果我使用IOUtils.copy(InputStream in, OutputStream out)然后我得到一個 null 指針異常。

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)

但是,如果我將輸入和 output stream 更改為文件而不是目錄,那么它可以正常復制。

有沒有辦法將屬於 jar 的目錄遞歸復制到文件系統?

正如 Reddymails 鏈接到的問題中提到的那樣,將所有資產文件放入一個 zip 文件中是一個很好的方法。

如果您想將資產文件作為單獨的條目保存在 .jar 中,問題是您將沒有要列出的目錄:

  • .jar 或 zip 文件中的目錄條目只是一個名稱; 沒有辦法“列出”它。
  • .jar 文件並不總是可以獲得的,因為ProtectionDomain.getCodeSource() 被允許返回 null
  • 有一些復雜的類加載器從目錄或 .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);
        }
    }
}

如果有人仍在尋找這個,我只是分享了一個完全這樣做的類:將資源目錄復制到文件系統中的目標位置。 可以在這里找到: https : //stackoverflow.com/a/58318009/738968

如果您有興趣從 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM