如何将资源添加到类路径中

17
如何将一个文件夹(例如一个包含艺术资源的资源文件夹)添加到NetBeans项目的类路径中?我成功地通过手动编辑项目的NB生成的jar文件(即其MANIFEST.MF文件+手动复制资源)做到了这一点,但是应该有一种方法告诉NetBeans注意这些资源。文件夹结构看起来像这样:
/project/art/
/project/dist/lib/
/project/dist/art/
/project/dist/project.jar
/project/lib/
/project/src/

我不想将艺术资源打包到jar文件中,因为我希望这些资源可以轻松交换。如果我将art文件夹添加到src文件夹中,NetBeans编译就没问题了,但是艺术资源最终会被打包到jar文件中。

将art文件夹添加到NetBeans项目库(属性->库->添加 JAR/文件夹)似乎不起作用,因为我遇到了一个错误“...\project\art是一个目录或无法读取。不复制库。”这又阻止了实际库文件夹的复制。

有什么想法吗?

最好的问候 Chris

根据gpeche的评论,提供两点观察: a) 在NetBeans中,将额外资源文件夹在项目属性 -> 库的“运行”选项卡中指定,而不是在“编译”选项卡中指定似乎没有太大差别。输出(因此错误)保持不变,即根本没有复制任何内容:

Created dir: C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\dist
C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\art is a directory or can't be read. Not copying the libraries.
Not copying the libraries.
Building jar: C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\dist\VocabularyTrainer.jar

另一个有趣的方面是,在“库”面板的帮助菜单中,并没有明确提到文件夹作为库。可能Netbeans中的按钮名称错误,只允许真实的jar文件吗?
将资源文件夹添加到库列表中确实会对MANIFEST.MF添加另一个条目。虽然问题较小,但classpath条目似乎始终期望资源文件夹是库文件夹的子文件夹(例如“lib/arts”),主要问题在于似乎缺少斜杠。如上所述,NB生成的MANIFEST.MF中的条目看起来像这样“lib/arts”(对我无效),而手动设置的“lib​​/arts /”呢?
我使用资源文件夹的方式类似于:
URL resource = getClass().getResource("/gui/refresh.png");
ImageIcon tmp = new ImageIcon(resource);

编辑:

根据Tushar的评论和这篇文章,我发现以下解决方案在功能和舒适性之间达到了可接受的平衡。

我覆盖了从Netbeans项目的基本'build.xml'文件中自动生成的'build-impl.xml'文件中创建MANIFEST.MF文件中的Class-Path的ANT目标。代码如下:

  <property name="art.classpath" value="art/" />

  <target name="-post-jar">
    <mkdir dir="${dist.dir}/art"/>
    <copy todir="${dist.dir}/art">
      <fileset dir="${basedir}/art">
        <!-- <exclude name="**/!source/**"/> if you want to exclude something... -->
      </fileset>
    </copy>
  </target>

  <target name="-init-macrodef-copylibs">
    <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
      <element name="customize" optional="true"/>
      <sequential>
        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
        <pathconvert property="run.classpath.without.build.classes.dir">
          <path path="${run.classpath}"/>
          <map from="${build.classes.dir.resolved}" to=""/>
        </pathconvert>
        <pathconvert pathsep=" " property="jar.classpath">
          <path path="${run.classpath.without.build.classes.dir}"/>
          <chainedmapper>
            <flattenmapper/>
            <globmapper from="*" to="lib/*"/>
          </chainedmapper>
        </pathconvert>
        <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
        <copylibs compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
          <fileset dir="${build.classes.dir}"/>
          <manifest>
            <attribute name="Class-Path" value="${jar.classpath} ${art.classpath}"/>
            <customize/>
          </manifest>
        </copylibs>
      </sequential>
    </macrodef>
  </target>

这样做的代价是,在Netbeans中进行开发时,我仍然需要将资源文件夹(例如“art”)添加到库列表中,以使项目在Netbeans中运行。这将导致MANIFEST.MF文件中出现额外的条目(“lib/art”),并且库将不会自动复制到“dist”文件夹中,同时会显示以下消息:

...\art is a directory or can't be read. Not copying the libraries.
Not copying the libraries.

据我所知,这种行为是有意的(强制将所有内容捆绑在一个jar包中),尽管仍在进行讨论。要创建一个真正的分发包,我需要从NB中的库列表中删除资源文件夹并重新构建。

当然,欢迎任何没有任何折衷的简化设置的想法。 :)

3个回答

15
  1. 将资源文件夹添加到类路径中:

    当您对基于 NetBeans Ant 的项目执行“清理和构建”操作时,它会在项目的根目录中创建一个 manifest.mf 文件。该文件也被包含在 JAR 文件中。修改此文件,并添加以下条目:

    Manifest-Version: 1.0
    X-COMMENT: Main-Class will be added automatically by build
    Class-Path: arts/  
    

    在类路径中,arts后面的斜杠很重要。

  2. 将arts资源文件夹包含在分发中

    在构建之后,将该文件夹复制到dist文件夹中,或添加一个ANT目标来将必需的资源复制到dist文件夹中。

    在build.xml文件中如下添加目标:

    <target name="-post-jar">
         <mkdir dir="${dist.dir}/resources"/>
         <copy todir="${dist.dir}/resources">
             <fileset dir="${basedir}/resources" />
         </copy>
     </target>
    
  3. 访问这些资源的代码:

    访问这些资源文件所需的代码如下:(在设计时间中不起作用,但肯定可以从JAR文件中工作)

  4. // pay attention to relative path
    URL resource = ClassLoader.getSystemResource("gui/refresh.png"); 
    ImageIcon tmp = new ImageIcon(resource);
    

    注意:位于项目根目录中的manifest.mf和build.xml文件可以在NetBeans IDE的“文件面板”中访问。


  1. 将某些内容添加到NB项目manifest.mf文件中(在这种情况下是Class-Path)似乎会覆盖其他任何可能存在的内容(例如添加到项目中的其他库)。有什么办法可以同时获取原始路径吗?例如,库本身将被复制。
  2. 对我来说,如果没有前导斜杠,它就无法正常工作 - 我必须添加该斜杠,然后它才能正常工作。
- ChristianS
我建议首先从NetBeans构建生成manifest.mf,然后使用这些默认类路径值加上您添加的其他目录路径。 - Tushar Joshi
请添加如何排除文件夹资源的指南,以便它不会包含在 .jar 文件中。 - GusDeCooL
有没有一种方法可以在不进入构建文件的情况下自动定制NB? - Warren Nocos

12

使用NetBeans 8.0.2:

  1. 右键单击项目。
  2. 选择属性
  3. 选择来源
  4. 点击添加文件夹,添加源程序包文件夹
  5. 选择资源所在的目录。
  6. 点击目录名称上的打开按钮。
  7. 点击确定关闭项目属性对话框。

这样就将资源添加到了项目中。

你会在导航窗格中看到添加的目录。

在其他项目中,现在可以使用这些资源。例如,读取一个图片:

BufferedImage zero = ImageIO.read(OCR.class.getResourceAsStream("/0.bmp"));

1
为了从Class-Path中删除lib/art并避免出现“是目录或无法读取”的错误,需要从路径中删除lib/art:
    <pathconvert property="run.classpath.without.build.classes.dir">
      <path path="${run.classpath}"/>
      <map from="${build.classes.dir.resolved}" to=""/>
      **<map from="${basedir}/art" to=""/> <!-- remove art from lib -->**
    </pathconvert>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接