在用 Ant 进行构建,部署,运行过程当中,发现一小问题,就是在运行时老是提示“系统找不到指定的文件”。害得我花了很多时间,最后终于弄清楚了问题的缘由。如下的错误代码(贴出来好让后面的人更容易找到这样贴子。:))html
[java] log4j:ERROR Could not read configuration file [HelloWroldLog4j.properties]. [java] java.io.FileNotFoundException: HelloWroldLog4j.properties (系统找不到指定的文件。) [java] at java.io.FileInputStream.open(Native Method) [java] at java.io.FileInputStream.<init>(FileInputStream.java:106) [java] at java.io.FileInputStream.<init>(FileInputStream.java:66) [java] at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:316) [java] at org.apache.log4j.PropertyConfigurator.configure(PropertyConfigurator.java:342) [java] H:\jstudy\ant\use_log4j\build\jar [java] File: true [java] at antstudy.HelloWorld.main(Unknown Source) [java] log4j:ERROR Ignoring configuration file [HelloWroldLog4j.properties]. [java] log4j:WARN No appenders could be found for logger (antstudy.HelloWorld). [java] log4j:WARN Please initialize the log4j system properly. |
因为文件中用到的PropertyConfigure.configure(String fileName),最终仍是利用了FileInputStream来读取配置文件的,因此fileName与FileInputStream构造时的fileName是相同的。因而我把问题简化为用 Ant 来进行只包括 FileInputStream 类的简单的代码,出现了相同问题。因为使用了相对路径,因此只要能够确认当前的目录,就能够解决问题了。利用 System.getProperty("user.dir") 终于找出来,当前用户工做目录是 Ant 的 build.xml 的路径。在查看了Ant 的文档, Java 任务能够设置 dir 属性来修改 JAVA 用户工做目录,固然要把 Java 任务的 fork 设置为 true。问题解决!
总结,问题的根本缘由仍是 Java 工做目录的设置。在用 Ant 进行执行 Java 任务时,JAVA用户工做目录是 builde.xml 全部的目录(若是没有修改的话),我想一般遇到我这样问题的人,都没有修改Java 任务的工做目录。
还有一个小问题没有获得解决,就是让 Ant 打包之后,这些配置文件怎么处理, *.properties 文件应不该该放到Jar包中呢?若是放在包中,
java
个人作法是,把当前工做目录设置到Jar包所在的目录,而且把*.properties文件复制到这个目录下面,也就,不对*.properties 文件打包。
不知道实际工做中是怎么解决这样的问题的。但愿有人会回答个人这个问题,先谢过了。
基本上找到了上面遗留问题的解决方法[续上]:
也就是 Jar 包中的文件的读取,在CSDN中有这样的贴子。能够去看看,讨论得很详细:如何读取自身Jar包中的文件 部份内容节选以下:
apache
在编写完Java程序后,打包成Jar时发布,会发现找不到Jar文件中的图片和文本文件,其缘由是程序中载入图片或文本文件时,使用了以当前工做路径为基准的方式来指定文件和路径。这与用户运行Jar包时的当前工做路径并不一致。
问题分析:
例如:以Windows为例说明,如下是开发项目“AAA”的部分代码,开发和调试时的根路径为D:\aaa,这样程序运行时当前路径为"D:\aaa",你们能够用System.getProperty("user.dir")方法求证当前用户工做路径。
并发
//下面代码使用了基于当前工做路径的方式指定了文件对象 File imageFile = new File("/images/sample.gif"); ImageIcon imageIcon = new ImageIcon(File.toURI); File iniFile = new File("/conf.ini"); FileInputStream fileInputStream = new FileInputStream(iniFile.toURI); /* *这样程序会去找如下两个文件: * D:\aaa\images\sample.gif * D:\aaa\conf.ini */ |
以上的代码应用绝对路径信息指定了文件对象,在开发和调试期(未打包前),是没有问题的,但在打包后,因为全部图片文件和文本文件都将打包到Jar文件中,因为System中的"user.dir"属性发生了变化,会形成用绝对路径的方式没法找到Jar文件中包含路径和文件。例如你们将上面的项目 “AAA”中的全部类文件、图片文件和文本文件等打包为E:\aaa.jar文件并发布,在用户执行该aaa.jar中的程序时,当前路径取决于用户运行该程序的当前路径。
例如: 在“E:\”目录下运行该程序:
app
E:\> java -jar aaa.jar |
此时用户的当前路径(System的user.dir属性)是“E:\”,而非开发者所指望的“E:\aaa”,因此会按如下路径来搜索文件:
E:\images\sample.gif
E:\conf.ini
可是全部的图片和文本文件包含在E:\aaa.jar文件中,因此会导致程序没法正常运行。
问题解决:
为了解决上述问题,推荐采用Java自己以类为基准的路径搜索方式。
例如:ui
/* *如下代码采用了以当前类为基准的路径指定方式。下面这行代码在运行时,会 *在jar文件中的根路径,搜索程序中用到的文件。 */ Reader reader = new InputStreamReader( getClass().getResourceAsStream("/image/Environment.ini")); ImageIcon i = new ImageIcon(getClass().getResource("/image/b1.gif")); |
以上两行代码采用了下面两条Java语句:spa
getClass().getResourceAsStream("FileName"); getClass().getResource("File"); |
含有这种代码的程序在运行时,以类(类路径)为基准,而不依赖当前路径(System中的user.dir)。
注意:上面的路径"/image/Environment.ini"若是写成"image/Environment.ini",将表示在类同路径下的路径(className/image/Environment.ini),这须要您必须将图片和文本等文件的保存路径,和程序中指定的路径二者保持一致。操作系统
maquan
> 什么文件能够? .bat 不行的话. .
> 哪些文件是能够的? image.? or?
问题的本质是这样的:若是你要用本身的程序去读文件,什么类型的文件都同样能够读到(就用你说的 getResource());可是,.BAT 文件是给操做系统用的,操做系统并不支持从 jar 文件里运行一个 BAT 文件。
因此,若是你必定要把 BAT 文件打到 jar 包里,那只能本身写程序读出这个文件的内容,再写到一个操做系统能看到的地方(也就是写到硬盘上的一个文件里),再让操做系统去运行它。
BTW: JAR 的意思就是 Java ARchive,顾名思义,就像老紫竹说的,“应该把非java文件放到外面”。
.net