使用InputStreamReader读取JAR内的目录

问题描述 投票:0回答:3

所以,我相信这个问题已经被问过一百万次了,我已经阅读了几个小时并尝试了一些人给出的几种选择,但没有一个对我有用。

我想列出应用程序 JAR 内某个目录内的所有文件,因此在 IDE 中这是可行的:

File f = new File(this.getClass().getResource("/resources/").getPath());

for(String s : f.list){
   System.out.println(s);
}

这给了我目录中的所有文件。

现在,我也尝试过:

InputStream in = this.getClass().getClassLoader().getResourceAsStream("resources/");
    InputStreamReader inReader = new InputStreamReader(in);
    Scanner scan = new Scanner(inReader);

    while (scan.hasNext()) {
        String s = scan.next();
        System.out.println("read: " + s);
    }

    System.out.println("END OF LINE");

从 IDE 中,它会打印目录中的所有文件。外部 IDE 打印:“END OF LINE”。

现在,我也可以在 Jar 中找到一个条目:

        String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
        JarFile jar = new JarFile(s);

            JarEntry entry = jar.getJarEntry("resources");

        if (entry != null){
            System.out.println("EXISTS");
            System.out.println(entry.getSize());
        }

我必须对该字符串进行一些可怕的编码。

无论如何...我无法获取 Jar 中“资源”目录内的资源列表...我该怎么做???

java file jar resources
3个回答
12
投票

如果不首先枚举 Jar 文件的内容,就无法简单地获取内部资源的过滤列表。

幸运的是,这实际上并不难(对我来说幸运的是你已经完成了大部分艰苦的工作)。

基本上,一旦您引用了

JarFile
,您只需询问其'
entries
并迭代该列表即可。

通过检查所需匹配的

JarEntry
名称(即
resources
),您可以过滤您想要的元素...

例如...

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ReadMyResources {

    public static void main(String[] args) {
        new ReadMyResources();
    }

    public ReadMyResources() {
        JarFile jf = null;
        try {            
            String s = new File(this.getClass().getResource("").getPath()).getParent().replaceAll("(!|file:\\\\)", "");
            jf = new JarFile(s);
            
            Enumeration<JarEntry> entries = jf.entries();
            while (entries.hasMoreElements()) {
                JarEntry je = entries.nextElement();
                if (je.getName().startsWith("resources")) {
                    System.out.println(je.getName());
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                jf.close();
            } catch (Exception e) {
            }
        }
    }

}

注意事项

这种类型的问题实际上有人问过。与其尝试在运行时读取 Jar 的内容,不如生成某种包含可用资源列表的文本文件。

这可以在创建 Jar 文件之前由构建过程动态生成。然后读取此文件(例如,通过

getClass().getResource()
),然后查找文本文件中的每个资源列表,这将是一个更简单的解决方案...恕我直言


11
投票

对于 Spring Framework 用户,请查看

PathMatchingResourcePatternResolver
执行以下操作:

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath:path/to/resource/*.*");

for (Resource resource : resources) {
    InputStream inStream = resource.getInputStream();
    // Do something with the input stream
}

0
投票

我的情况是读取资源内的目录:

由于我的需求是将资源目录转换为io.File,最后看起来像这样:

public static File getResourceDirectory(String resource) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL res = classLoader.getResource(resource);
        File fileDirectory;
        if ("jar".equals(res.getProtocol())) {
            InputStream input = classLoader.getResourceAsStream(resource);
            fileDirectory = Files.createTempDir();
            List<String> fileNames = IOUtils.readLines(input, StandardCharsets.UTF_8);
            fileNames.forEach(name -> {
                String fileResourceName = resource + File.separator + name;
                File tempFile = new File(fileDirectory.getPath() + File.pathSeparator + name);
                InputStream fileInput = classLoader.getResourceAsStream(resourceFileName);
                FileUtils.copyInputStreamToFile(fileInput, tempFile);
            });
            fileDirectory.deleteOnExit();
        } else {
            fileDirectory = new File(res.getFile());
        }

        return fileDirectory;
    }

如果资源在jar中,我们将其复制到临时目录中,该目录将在应用程序端删除。 然后调用

getResourceDirectory("migrations")
返回给我
io.File
目录以供进一步使用。

© www.soinside.com 2019 - 2024. All rights reserved.