导出的JAR无法读取本地文件

时间:2016-08-21 04:37:39

标签: java eclipse file fileinputstream objectinputstream

我的Java应用程序在名为“assets”的顶级文件夹中有一个名为“classes”(简单{@iterate items="ab,cd,ef,12"} Item: {.}{~n} {/iterate} )的本地文件。当我从Eclipse运行下面的代码时,文件读取没问题。

{#iterate}

当我将我的应用程序导出为JAR并在另一台计算机上运行时,我在第3行获得List<String>。我将“assets”文件夹添加到构建路径中,因此它应该在JAR中。

有人知道这里有什么问题吗?

1 个答案:

答案 0 :(得分:1)

FileOutputStream只会打开一个本地文件。它应该是绝对的(/home/user/...c:\temp\...)或相对于当前目录。例如,在Windows上,默认情况下,该目录是包含JAR的目录。

如果您打算将classes文件打包到 JAR中,那么您应该使用getResourceAsStream,如@guleryuz所述。该路径应该是从CLASSPATH根(即JAR文件的根)开始的绝对路径,如"/asset‌​s/classes",或者(更好)相对于调用类的包。

说到课程,我强烈反对使用getClass(),因为它是一种多态方法。获取类有两种方法:通过在对象上调用getClass()或访问静态class“字段”。如果您的MyClass实例名为myObject,则myObject.getClass()MyClass.class基本相同。但!如果您的课程被其他论坛中的某个课程覆盖,例如TheirClass,那么,对于TheirClass的实例,getClass()将返回TheirClass.class,即使您正在呼叫来自您的代码的getClass()。因此,除非您的班级被声明为final,否则使用getClass().getResource...总是一个坏主意,因为您永远不知道有人会超越您的班级。你不应该知道甚至不关心!

考虑到所有这些,比如说,你在名为MyClass的包中有一个名为my.package的类。 JAR可以具有以下结构:

my/
    package/
        MyClass.class
        assets/
            classes

然后,调用MyClass.class.getResourceAsStream("assets/classes")就可以了。或者,可能是MyClass.class.getResourceAsStream("/my/package/assets/classes")。请注意,绝对路径 not 从项目目录开始,您可能在其中srcsrc/main或您的构建系统使用的任何内容。它是相对于CLASSPATH根(右边,绝对路径相对到CLASSPATH根目录,即使这看起来很混乱)。也就是说,它从包的目录开始。

最后但并非最不重要的是,如果您使用类似Maven的构建系统(例如Maven或Gradle),那么Java源代码将转到src/main/java,但是像您的文件这样的资源文件会转到{{ 1}}。它们最终位于JAR文件中的完全相同的位置。也就是说,src/main/resources被编译为src/main/java/package/MyClass.javapackage/MyClass.class进入src/main/resources/package/assets/classes。但是为了让构建系统弄清楚如何处理文件,您必须将它们放在正确的目录中:package/assets/classes转到*.java,资源转到java

因此,假设类似Maven的约定,项目结构应该是

resources

鉴于这样的结构,您将获得具有上述结构的JAR文件。看起来有点疯狂,但是一旦掌握了它就非常有用。

如果您没有使用类似Maven的构建系统,那么我不知道如何配置Eclipse。不同的IDE可能有自己的约定,我总是使用Maven和Eclipse。例如,有些IDE喜欢将Java源代码和资源放在同一个目录树中。