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

Kev*_*vin 5 java file-io

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

java/
resources/
    assets/
        file1.txt
        file2.txt
        subdir/
            file3.txt
Run Code Online (Sandbox Code Playgroud)

我想将资产目录(递归地)复制到文件系统上的某个位置。如果我使用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)
Run Code Online (Sandbox Code Playgroud)

但是,如果我更改输入和输出流,使它们是文件而不是目录,那么它复制得很好。

有没有办法将 jar 的一部分目录递归复制到文件系统?

VGR*_*VGR 2

正如 Reddymails 链接的问题中提到的,将所有资产文件放入 zip 文件中是一个很好的方法。

\n\n

如果您想将资产文件作为单独的条目保留在 .jar 中,问题是您将没有要列出的目录:

\n\n
    \n
  • .jar 或 zip 文件中的目录条目只是一个名称;没有办法 \xe2\x80\x9clist\xe2\x80\x9d 它。
  • \n
  • .jar 文件并不总是可获取的,因为ProtectionDomain.getCodeSource() 允许返回 null
  • \n
  • 有一些复杂的类加载器从目录或 .jar 文件以外的源读取。
  • \n
\n\n

您可以让构建过程在打包之前列出文本文件中的条目(因为您毕竟知道它们是什么),并将该文本文件包含在您的 .jar 中。然后在运行时复制它们就像从该文件中读取一样简单:

\n\n
Path assetDir = /* ... */;\n\ntry (BufferedReader listFile = new BufferedReader(\n        new InputStreamReader(\n            getClass().getResourceAsStream("assets-list.txt"),\n            StandardCharsets.UTF_8))) {\n\n    String assetResource;\n    while ((assetResource = listFile.readLine()) != null) {\n        Path assetFile = assetDir.resolve(assetResource);\n        Files.createDirectories(assetFile.getParent());\n        try (InputStream asset = getClass().getResourceAsStream(assetResource)) {\n            Files.copy(asset, assetFile);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n