61

我在资源文件夹中有文件。例如,如果我需要从资源文件夹中获取文件,我会这样做:

File myFile= new File(MyClass.class.getResource(/myFile.jpg).toURI());             
System.out.println(MyClass.class.getResource(/myFile.jpg).getPath());

我已经测试过,一切正常

路径是

/D:/java/projects/.../classes/X/Y/Z/myFile.jpg

但是,如果我使用Maven创建 jar 文件:

mvn package

...然后启动我的应用程序:

java -jar MyJar.jar

我有以下错误:

Exception in thread "Thread-4" java.lang.RuntimeException: ხელმოწერის განხორციელება შეუძლებელია
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
        at java.io.File.<init>(File.java:363)

...文件的路径是

file:/D:/java/projects/.../target/MyJar.jar!/X/Y/Z/myFile.jpg

当我尝试从资源文件夹中获取文件时会发生此异常。在这一行。为什么?为什么在 JAR 文件中有这个问题?你怎么看?

还有另一种方法来获取资源文件夹路径吗?

4

3 回答 3

91

你应该使用

getResourceAsStream(...);

当资源被捆绑为 jar/war 或任何其他单个文件包时。

看到的事情是,一个 jar 是一个包含许多文件的单个文件(有点像一个 zip 文件)。从 Os 的 pov 来看,它是一个文件,如果您想访问part of the file(您的图像文件),您必须将其用作流。

文档

于 2013-08-05T10:06:03.647 回答
11

这是 Eclipse RCP / Plugin 开发人员的解决方案:

Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
   URL resolvedFileURL = FileLocator.toFileURL(fileURL);

   // We need to use the 3-arg constructor of URI in order to properly escape file system chars
   URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
   File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
    e1.printStackTrace();
} catch (IOException e1) {
    e1.printStackTrace();
}

FileLocator.toFileURL(fileURL)使用而不是非常重要resolve(fileURL) ,因为当插件被打包到 jar 中时,这将导致 Eclipse 在临时位置创建一个解压缩版本,以便可以使用 File 访问该对象。例如,我猜 Lars Vogel 在他的文章中有一个错误 - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

于 2014-05-30T13:45:05.010 回答
2

当我在公司从事一个项目时,我遇到了同样的问题。首先,URI 不是分层问题是因为您可能使用“ / ”作为文件分隔符。

您必须记住,“/”适用于 Windows,并且从操作系统到操作系统会发生变化,在 Linux 中可能会有所不同。因此使用File.seperator

所以使用

this.getClass().getClassLoader().getResource("res"+File.separator+"secondFolder")

可能会删除不分层的 URI。但是现在您可能会遇到空指针异常。我尝试了许多不同的方法,然后使用 JarEntries 类来解决它。

File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
        String actualFile = jarFile.getParentFile().getAbsolutePath()+File.separator+"Name_Of_Jar_File.jar";
        System.out.println("jarFile is : "+jarFile.getAbsolutePath());
        System.out.println("actulaFilePath is : "+actualFile);
        final JarFile jar = new JarFile(actualFile);
        final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
        System.out.println("Reading entries in jar file ");
        while(entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            final String name = jarEntry.getName();
            if (name.startsWith("Might Specify a folder name you are searching for")) { //filter according to the path
                System.out.println("file name is "+name);
                System.out.println("is directory : "+jarEntry.isDirectory());
                File scriptsFile  = new File(name);
                System.out.println("file names are : "+scriptsFile.getAbsolutePath());

            }
        }
        jar.close();

您必须在此处明确指定 jar 名称。因此,使用此代码,这将为您提供 jar 文件夹内的目录和子目录。

于 2016-04-29T12:48:32.660 回答