前端时间,需要将java代码打成可运行的jar包,jar内的代码需要读取外部的配置文件。在处理路径上,花了点时间,先整理一下:

jar读取内部外部文件的方式: 不能把jar理解成一个文件夹,因此不能通过常规的文件路径方式来读取 jar内部的文件。例如 xml文件、dll文件等。如果希望打包时将一些文件打入jar包,无论jar部署在哪,都能读取jar内文件的话,就需要修改 jar内代码读取文件的方式:
读取jar内文件需要 getRescourAsStrean的方式:

//返回读取指定资源的输入流 

 InputStream is=this.getClass().getResourceAsStream("/resource/res.txt"); 

 BufferedReader br=new BufferedReader(new InputStreamReader(is)); 

 String s=""; 

 while((s=br.readLine())!=null) 

 System.out.println(s);



需要注意的是 需要将文件建在类路径下,如src下,打包时,才能打到jar包内。
如果jar包内代码引用了第三方的jar,打包时,需要通过fatJar插件,将第三方jar解压,按类的结构放在和自己代码同级的目录下,自己的代码才能根据类的路径,找到第三方类。fatJar自动做了这些事。

读取jar外的文件。可参见一博客:http://tomfish88.iteye.com/blog/971255
读取jar外的文件灵活的方式首先获取当前jar运行的路径,该路径即类路径。通过类路径获取jar外部的文件。
获取类路径的方式可通过找当前运行的类的文件位置来找:(PathUtil 为自定义的获取类路径的工具类)
网上推荐方式整理:
(1)classPath = PathUtil.class.getClass().getResource("/").getPath().replaceAll("%20", " ");
(2)classPath=ClassLoader.getSystemResource("").getPath().replaceAll("%20", " ");
(3)classPath=System.getProperty("user.dir")
(4)classPath=new File("").getAbsolutePath()
(5)classPath=Thread.currentThread().getContextClassLoader().getResource("").getPath().replaceAll("%20", " ");
(6)classPath=PathUtil.class.getClassLoader().getResource("").getPath().replaceAll("%20", " ");


经实际打包运行测试,只有 1 和2 能在打包运行环境下获取到正确的类路径。其他或者报错、或者获取到其他的路径了。原因还望赐教,没深入细研究。
另外对于 (1),网上有好多的写法,如:PathUtil.getClass().getResource("/").getPath().replaceAll("%20", " ");
该写法在Eclipse下运行和实际打包运行时,个人测试,实际打包运行会报错。对于java内部如何寻找ClassLoader类,不是很明白,所以也不清楚各种写法的报错原因。

另外就是 getResource获取的URL路径,空格处是用20%代替的,而File的方式处理绝对路径时不识别20%,因此需要对20%做处理。

Spring加载xml时采用了同样的方式处理xml文件,因此 有spring配置的jar,读spring配置文件时,既可以读取jar内部的xml文件,也可以读取与jar在同一目录的外部xmL文件。log4j同样。