8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

从 jar 中读取资源文件

GJohannes 1月前

38 0

我想从我的 jar 中读取资源,如下所示:File file;file = new File(getClass().getResource(\'/file.txt\').toURI());BufferedReader reader = new BufferedReader(new FileRea...

我想从我的 jar 中读取资源,如下所示:

File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferedReader reader = new BufferedReader(new FileReader(file));

//Read the file

在 Eclipse 中运行它时工作正常,但如果我将它导出到 jar,然后运行它,就会出现 IllegalArgumentException:

Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical

我真的不知道为什么,但经过一些测试,我发现如果我改变

file = new File(getClass().getResource("/file.txt").toURI());

file = new File(getClass().getResource("/folder/file.txt").toURI());

然后它就起到相反的作用(它在 jar 中可以工作,但在 eclipse 中不行)。

我正在使用 Eclipse,包含我的文件的文件夹位于类文件夹中。

帖子版权声明 1、本帖标题:从 jar 中读取资源文件
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由GJohannes在本站《file》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我不确定原始问题是否涉及 Spring。上一条评论中的链接指向另一个问题中有关 Spring 的具体答案。我相信

  • 您不需要尝试将资源作为 File 只需要求 ClassLoader InputStream InputStream 资源的 getResourceAsStream :

    try (InputStream in = getClass().getResourceAsStream("/file.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
        // Use resource
    }
    

    只要 file.txt 资源在类路径上可用,那么无论资源 file.txt 是在 classes/ 目录中还是在 jar .

    这种 URI is not hierarchical 情况的原因是 jar 文件中资源的 URI 看起来类似于以下内容: file:/example.jar!/file.txt 像读取普通文件一样 jar 读取 zip File .

    以下答案很好地解释了这一点:

    • 如何从 Java jar 文件中读取资源文件?
    • Java Jar 文件:使用资源错误:URI 不是分层的
  • 谢谢,这很有帮助,代码运行完美,但我有一个问题,我需要确定 InputStream 是否存在(如 File.exists()),这样我的游戏才能判断是否使用默认文件。谢谢。

  • 哦,顺便说一下,getClass().getResource(\'**/folder**/file.txt\') 使其工作的原因是因为我将该文件夹与我的 jar 放在同一目录中:)。

  • 如果资源不存在,getResourceAsStream 将返回 null,因此可以进行“存在”测试。

  • 当然...不要忘记关闭 inputStream 和 BufferedReader

  • 您无法像读取普通文件那样读取 jar(zip 文件)中的条目。这很糟糕,因为有大量库函数需要文件路径作为输入。

  • 要访问 jar 中的文件,您有两个选择:

    • p1

    • p2

    当 jar 作为插件使用时,第一个选项可能不起作用。

  • 非常感谢您给出这个出色的答案...第二种选择的另一个好处是它也可以用于主方法,因为 getClass() 只能用于实例,而不能用于静态方法。

  • 我以前遇到过这个问题,我为加载设置了后备方法。基本上第一种方法适用于 .jar 文件,第二种方法适用于 eclipse 或其他 IDE。

    public class MyClass {
    
        public static InputStream accessFile() {
            String resource = "my-file-located-in-resources.txt";
    
            // this is the path within the jar file
            InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource);
            if (input == null) {
                // this is how we load file within editor (eg eclipse)
                input = MyClass.class.getClassLoader().getResourceAsStream(resource);
            }
    
            return input;
        }
    }
    
  • 对我来说不起作用...我在 jar 中的资源中有 .wsdl...但它仍然无法解析 wsdl

  • Park 1月前 0 只看Ta
    引用 13

    到目前为止(2017 年 12 月),这是我发现的唯一一个在 IDE 内部和外部

    使用 PathMatchingResourcePatternResolver

    注意: 它也适用于 spring-boot

    在此示例中,我正在读取位于 src/main/resources/my_folder 的

    try {
        // Get all the files under this inner resource folder: my_folder
        String scannedPackage = "my_folder/*";
        PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
        Resource[] resources = scanner.getResources(scannedPackage);
    
        if (resources == null || resources.length == 0)
            log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
        else {
            for (Resource resource : resources) {
                log.info(resource.getFilename());
                // Read the file content (I used BufferedReader, but there are other solutions for that):
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    // ...
                    // ...                      
                }
                bufferedReader.close();
            }
        }
    } catch (Exception e) {
        throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
    }
    
  • 问题是某些第三方库需要文件路径名而不是输入流。大多数答案都没有解决这个问题。

    在这种情况下,一种解决方法是将资源内容复制到临时文件中。以下示例使用 jUnit 的 TemporaryFolder .

        private List<String> decomposePath(String path){
            List<String> reversed = Lists.newArrayList();
            File currFile = new File(path);
            while(currFile != null){
                reversed.add(currFile.getName());
                currFile = currFile.getParentFile();
            }
            return Lists.reverse(reversed);
        }
    
        private String writeResourceToFile(String resourceName) throws IOException {
            ClassLoader loader = getClass().getClassLoader();
            InputStream configStream = loader.getResourceAsStream(resourceName);
            List<String> pathComponents = decomposePath(resourceName);
            folder.newFolder(pathComponents.subList(0, pathComponents.size() - 1).toArray(new String[0]));
            File tmpFile = folder.newFile(resourceName);
            Files.copy(configStream, tmpFile.toPath(), REPLACE_EXISTING);
            return tmpFile.getAbsolutePath();
        }
    
  • 这一点被一笔带过了。谢谢你的记录。我很好奇除了 JUnit 之外还有哪些其他选择。

  • Ymi 1月前 0 只看Ta
    引用 16

    由于 resourceName 应始终使用 / 作为分隔符,而 decomposePath 中的 File 操作则使用系统特定的文件分隔符,因此该方法与 path.split(\'/\') 相比不仅不必要地复杂,甚至是不正确的。此外,当您不使用 .toArray(new String[0])) 的结果时,为什么调用它还不清楚。

  • 什么是文件夹,列表来自哪个库,什么是 REPLACE_EXISTING……?请在您的帖子中提供完整的信息。

  • 就我而言,我终于做到了

    import java.lang.Thread;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    final BufferedReader in = new BufferedReader(new InputStreamReader(
          Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt"))
    ); // no initial slash in file.txt
    
  • 奇怪的是,这也是我使用嵌套资源时的解决方案。不过,我想知道为什么它似乎在其他发布的答案中与斜线一起使用。

  • @ElectRocnic 我认为这是因为路径的解释方式。\'/file.txt\' 表示切换到当前目录并打开 file.txt,而 \'file.txt\' 表示从当前位置打开 file.txt。它们都指向同一个位置。对我来说,两者都可以在 Windows 系统中运行。

返回
作者最近主题: