Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从java访问外部.jar资源_Java_User Interface_Resources_Jar_Load - Fatal编程技术网

从java访问外部.jar资源

从java访问外部.jar资源,java,user-interface,resources,jar,load,Java,User Interface,Resources,Jar,Load,我正在从事一个多模块Java项目,它由Eclipse中相互依赖的多个项目组成,现在为了添加GUI主题支持,我创建了一个Java项目,它不包含任何代码,只包含GUI所需的图标和图片,我将它做成了一个Java项目,以便Maven将其构建到.jar中。现在有一个主应用程序将多个项目加载到一个主GUI中,该GUI从当前实际模块中的资源中获取图标。我只想从外部dummy.jar加载所有这些资源,该外部dummy.jar包含在主应用程序的.jar的类路径中。到目前为止,我找到的每一种方法似乎都不起作用。ja

我正在从事一个多模块Java项目,它由Eclipse中相互依赖的多个项目组成,现在为了添加GUI主题支持,我创建了一个Java项目,它不包含任何代码,只包含GUI所需的图标和图片,我将它做成了一个Java项目,以便Maven将其构建到.jar中。现在有一个主应用程序将多个项目加载到一个主GUI中,该GUI从当前实际模块中的资源中获取图标。我只想从外部dummy.jar加载所有这些资源,该外部dummy.jar包含在主应用程序的.jar的类路径中。到目前为止,我找到的每一种方法似乎都不起作用。jar不包含实际的java.class,因此没有可引用的类加载器。是否有其他方法可以在不提取.jar的情况下加载图片?

您可以尝试以下三种方法:

在资源jar中创建一个虚拟类,您可以使用它来获取类加载器引用。 如果您知道jar文件所在的位置,请使用URLClassLoader。 通过扩展java.lang.ClassLoader,您始终可以创建自己的类加载器。
将外部jar文件视为zip存档,并读取图像/资源,如下所示:

public ZipStuff(String filename) throws IOException
{
    ZipFile zf = new ZipFile(filename);
    Enumeration<? extends ZipEntry> entries = zf.entries();

    while (entries.hasMoreElements()) {
      ZipEntry ze = entries.nextElement();
      ImageIcon ii = new ImageIcon(ImageIO.read(zf.getInputStream(ze)));
      JLabel l = new JLabel(ii);
      getContentPane().add(l);
    }
    setVisible(true);
    pack();
}

在本例中,我有一个jar文件,其中只有一个映像,我将其加载到JLabel中。ZipStuff类是一个JFrame。

您可以获得所有资源类路径上的所有jar文件都应该工作,即使没有类:

    Enumeration<URL> resources = null;
    try {
        resources = Thread.currentThread().getContextClassLoader().getResources(someResource);
    } catch (Exception ex) {
         //no op      
    }
    if (resources == null || !resources.hasMoreElements()) {
        resources = ClasspathReader.class.getClassLoader().getResources(someResource);
    }
此时,您应该只有jar:file资源,所以。。。 拆分如下所示的字符串:

public ZipStuff(String filename) throws IOException
{
    ZipFile zf = new ZipFile(filename);
    Enumeration<? extends ZipEntry> entries = zf.entries();

    while (entries.hasMoreElements()) {
      ZipEntry ze = entries.nextElement();
      ImageIcon ii = new ImageIcon(ImageIO.read(zf.getInputStream(ze)));
      JLabel l = new JLabel(ii);
      getContentPane().add(l);
    }
    setVisible(true);
    pack();
}
jar:file:/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar/组织/节点/

进入这个

/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar

还有这个

/组织/节点/

以下是执行上述操作的代码,其中没有令人讨厌的错误检查:

        String[] split = resource.toString().split(":");
        String[] split2 = split[2].split("!");
        String zipFileName = split2[0];
        String sresource = split2[1];

        System.out.printf("After split zip file name = %s," +
                " \nresource in zip %s \n", zipFileName, sresource);
现在我们有了zip文件名,因此可以读取它:

        ZipFile zipFile = new ZipFile(zipFileName);
现在我们可以遍历它的条目:

        Enumeration<? extends ZipEntry> entries = zipFile.entries();

        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();

            /* If it is a directory, then skip it. */
            if (entry.isDirectory()) {
                continue;
            }

            String entryName = entry.getName();
            System.out.printf("zip entry name %s \n", entryName);
我之前做了两个技巧来检查它是否是一个目录

    boolean isDir = !someResource.endsWith(".txt");
这只会起作用,因为我正在寻找以.txt结尾的资源,如果它不以.txt结尾,我假设它是一个dir/foo/dir和/foo/dir/both

另一个窍门是:

    if (someResource.startsWith("/")) {
        someResource = someResource.substring(1);
    }
类路径资源永远不能真正以斜杠开始。逻辑上是这样,但事实上你必须去掉它。这是类路径资源的已知行为。它使用斜杠,除非资源位于jar文件中。底线是,剥离它,它总是有效的

我们需要得到这个该死的东西的实际文件名。文件名是条目名称的一部分。 其中是/foo/bar/foo/bee/bar.txt,我们想要的是“bar.txt”,它是文件名。回到我们的while循环中

        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            ...
            String entryName = entry.getName(); //entry is zipEntry
            String fileName = entryName.substring(entryName.lastIndexOf("/") + 1);


            /** See if the file starts with our namespace and ends with our extension. */
            if (fileName.startsWith(namespace) && fileName.endsWith(".txt")) {
接下来,我们看看这些条目是否符合我们的标准,如果符合,则将文件的内容读取到System.out

          try (Reader reader = new InputStreamReader(zipFile.getInputStream(entry))) {
                    StringBuilder builder = new StringBuilder();
                    int ch = 0;
                    while ((ch = reader.read()) != -1) {
                        builder.append((char) ch);

                    }
                    System.out.printf("zip fileName = %s\n\n####\n contents of file %s\n###\n", 
                    entryName, builder);
                } catch (Exception ex) {
                    ex.printStackTrace();//it is an example/proto :)
                }
            }

您可以在这里看到完整的示例:。

这个问题看起来像是.jar的副本,它不包含实际的java.class,因此没有可引用的类加载器。如果Jar位于应用程序的运行时类路径上,则应使用上下文类加载器中的getResource查找资源,该加载器具有“从根目录开始的路径”,例如/path/to/the.pngIt实际上是我的一个简单错误,我使用了不存在的路径。显然,无论从何处调用getResource,Java都可以从类路径获取资源。有人向我解释说,Java在运行时基本上是用所有使用过的JAR构建一个文件系统,因此访问非常简单,并且是全局可用的。谢谢大家的建议!
          try (Reader reader = new InputStreamReader(zipFile.getInputStream(entry))) {
                    StringBuilder builder = new StringBuilder();
                    int ch = 0;
                    while ((ch = reader.read()) != -1) {
                        builder.append((char) ch);

                    }
                    System.out.printf("zip fileName = %s\n\n####\n contents of file %s\n###\n", 
                    entryName, builder);
                } catch (Exception ex) {
                    ex.printStackTrace();//it is an example/proto :)
                }
            }