FileUtil:获取jar所在目录
最近做一个企业应用,需要在项目打包后,生成的jar包所在目录生成一个临时目录。
开始,直接取了user.dir,可打包后发现出不对:user.dir为用户工作目录。
那么只能从class loading入手了,从加载资源class计算URL得到一个该目录(这样能得到结果,就是不知道有什么风险?我在windows和linux上测试过)。
我的FileUtil代码如下:
public class FileUtil {private static final Log logger = LogFactory.getLog(FileUtil.class);/** * syslog应用程序被打包成为jar包发布。在syslog服务中,需要在jar文件位置创建临时文件夹,以保存数据。 * 临时文件夹:1 读文件中,ftp到中央日志服务的文件,被放到临时文件夹后再读。 * 2 分析会后的日志,保存一个月。如果选择了备份,则把每天需要备份的文件移动到一个临时备份文件夹。 * 逻辑:如果getDirFromClassLoader()方法计算不出来path,就取System.getProperty("user.dir")用户工作目录 * */public static String getJarDir(){String path = getDirFromClassLoader();if(path == null){path = System.getProperty("user.dir");}return path;}/** * 从通过Class Loading计算路径: * 1 class文件通过jar包加载: * 如果为jar包,该包为d:/test/myProj.jar * 该方法返回d:/test这个目录(不受用户工作目录影响) * 提示:在jar包加载 的时候,通过指定加载FileUtil的class资源得到jar:<url>!/{entry}计算出加载路径 * 2 class文件直接被加载: * 如果是web工程,class文件放在D:\tools\apache-tomcat-5.5.27\webapps\webProj\WEB-INF\classes * 该方法返回D:\tools\apache-tomcat-5.5.27\webapps\webProj\WEB-INF * 即返回放class文件夹的上一层目录。 * */private static String getDirFromClassLoader(){try {String path = FileUtil.class.getName().replace(".", "/");path ="/"+path+".class";URL url=FileUtil.class.getResource(path);String jarUrl= url.getPath();if(jarUrl.startsWith("file:")){if(jarUrl.length()>5){jarUrl = jarUrl.substring(5);}jarUrl = jarUrl.split("!")[0];}else{jarUrl = FileUtil.class.getResource("/").toString().substring(5);}File file = new File(jarUrl);return file.getParent();} catch (Exception e) {}return null;}/** * 找出指定目录及其子目录下,满足指定后缀的文件的绝对路径。 * 提示:方法中出现异常被内部捕获。 * @param dir 指定目录 * @param suffix 文件名后缀 * * @throws IllegalArgumentException * */public static List<String> find(String dir,String suffix){List<String> list = new ArrayList<String>();try {File file = new File(dir);if(file.exists() && file.isDirectory()){find(file, suffix, list);}else{throw new IllegalArgumentException("param \"dir\" must be an existing directory .dir = "+dir);}} catch (Exception e) {logger.error("gcw:find(dir,suffix) - "+e.getMessage());}return list;}/** * 递归遍历,查找满足后缀的文件 * @param dirFile 必须为一个存在的目录.不能为null * @param suffix * @param list 递归遍历目录记录满足后缀的文件的绝对路径。 * */private static void find(File dirFile,String suffix,List<String> list){if(dirFile.exists() && dirFile.isDirectory()){File[] subFiles = dirFile.listFiles();for(File subFile : subFiles) {if(subFile.isDirectory()){find(subFile, suffix, list);}else{String path = subFile.getAbsolutePath();if(path.endsWith(suffix)){list.add(path);}}}}else{throw new IllegalArgumentException("param \"dir\" must be an existing directory .dir = "+dirFile.getAbsolutePath());}}}??
jar中加载资源不熟悉的,可以看看javaee的这个讨论:主题:深入jar包:从jar包中读取资源文件
new File("").getAbsolutePath()吗? 8 楼 nishizhutoua 2009-12-15 理论上用class.getProtectionDomain().getCodeSource().getLocation().getFile();比较准.不过有两个需要注意的:
1.返回如果是个文件说明是Jar包形式,返回的是jar,如果是目录说明是class,返回的是class所在的目录.
2.如果加载class的classLoder是一个自定义,那个这个方法很可能不支持,因为自定义的classLoder可能没有完成这部分功能.
9 楼 CapsLk 2009-12-15 mxswl 写道clazz.getProtectionDomain().getCodeSource().getLocation()
谢谢mxswl的提示! 这样拿到的URL直接可以getFile或者getPath得到文件系统的路径。我的做法太繁琐了。有时间在研究研究security 包。
关于new File("")与user.dir类似。