写一个SSLsocket 的类,需要设置证书,如下:
System.setProperty("javax.net.ssl.trustStore","C:\Tomcat 5.5\webapps\expstudent\cacerts.store");为增加移植性,我想使用相对路径 "/../../cacerts.store",可是这样写程序就找不到证书文件了。这个类是放在C:\Tomcat 5.5\webapps\expstudent\WEB-INF\classes 下面的,经测试类文件中根目录 "/" 是指
C:\Tomcat 5.5\webapps\expstudent\WEB-INF\classes
所以我想使用 "/../../cacerts.store",可是为什么不行呢?另外相同文件夹下的另一个类中,我使用了相同的方法是可以找到文件的:
InputStream is = this.getClass().getResourceAsStream("/../../upload/"+myFilename); 
上面这行是对的,为什么换一个类换一个函数就不行了呢?难道是因为System.setProperty()不支持相对路径?请问有什么通用方法解决路径移植性问题么?

解决方案 »

  1.   

    那我只能用getrealpath() 获得绝对路径了么?
    可是对不同服务器这个方法好像得到的路径最后一个字符会有带"/"不带"/"的区别。
    以前用这个方法,经常是换个操作系统或者换个服务器就不对了
    都说“一次编写,到处运行”,我咋是“运行一次,编写一次”
      

  2.   

    我认为你需要用getRealPath()方法获取路径
      

  3.   

    那怎么处理路径字符串最后一个字符有没有"/"的问题呢?不同服务器可能结果不同。
    我现在的想法是文件名前面都加上"/", 既"/filename"
    然后得到全路径,把所有"//","\/"都替换成"/", 不过这样会不会太笨了呢
      

  4.   

    首先,LZ 要明确一点,这个问题不是 System.setProperty() 支持不支持相对路径的问题,而是使用了System.getProperty("javax.net.ssl.trustStore") 那段程序支持不支持相对路径的问题。有兴趣的话,你可以跟踪到那段程序去看一看,也许会有帮助。现在,你可以试着把相对路径写成 "../../cacerts.store" 看看,也就是说,把你原来程序中所谓“相对路径”的那个前导 "/" 去掉。至于你说的 this.getClass().getResourceAsStream("/../../upload/"+myFilename); 其实严格说,这个并不是相对路径,这更像是个绝对路径,因为在 getResourceAsStream() 的上下文中,"/" 就是指 CLASSPATH,其它的东西都是在这个基础上开始查找的。这一点并不完全等同于在文件系统里找一个文件,尽管语法形式上有些类似。
      

  5.   

    很高兴 LZ 能想到用测试的方法试图找到“相对路径的参考起点”。不过我仔细想了一下,你这里得到的结论是有问题的。你这里所谓的“根目录”,应该说的是 getResourceAsStream() 意义下的“根”,而不是 new File(".") 意义下的“根”。所以,我在 5 楼回帖中说的相对路径的写法应该也是不对的。你应该再用 new File(".").getAbsolutePath() 的方法测试一下所谓的“相对路径的参考起点”,然后再决定你的“相对路径”应该怎么写,或者直接拼出绝对路径。一般来说,这个参考起点缺省时应该是 tomcat\bin。其实,上面这种方法也不好,它的可移植性比较有问题。我认为更正宗的办法是在启动 tomcat 的时候,提供一个 expstudent.home 之类的环境变量,然后程序中以此为“相对路径的参考起点”构造出 cacerts.store 的绝对路径,再调用 System.setProperty()。
      

  6.   

    用System.getProperty("user.dir")
    在拼出你的文件路径
      

  7.   

    文件的分隔符可以用File.separator 它是系统相关的
      

  8.   

    支持  .
    不同的系统下File.separator 会有不同的表现形式.
      

  9.   

    经测试System.setProperty()的“相对路径的参考起点”与以下2个方法得到路径相同
    new File(".").getAbsolutePath() 
    System.getProperty("user.dir") 
    为什么不同函数中"/"的位置就不同了呢?不是有种说法 “服务器端解析的路径其根都是web application的目录”么,怎么不一样呢
      

  10.   

    你的意思是不是程序中先得到 expstudent.home ,再拼出要读取文件的绝对路径?
    那不又回到拼绝对路径的老路么。
    不过目前看来由于不同函数中"/" ".." 的意义都会不同,似乎还是拼绝对路径更简单了
      

  11.   

    拼绝对路径并不可怕  :)
    甚至不用关心 / 和 \ 的差异。请参考下面的程序,在运行的时候需要增加命令行参数 -Dexpstudent.home="C:\Tomcat 5.5\webapps\expstudent"
            String refRoot = System.getProperty("expstudent.home");
            System.out.println(refRoot);
            String abspath = new File(new File(refRoot), "certs/cacerts.store").getCanonicalPath();
            System.out.println(abspath);
      

  12.   

    说实话没看明白获取绝对路径的方法我一般用request.getSession().getServletContext().getRealPath("");
    可以得到类似String refRoot = System.getProperty("expstudent.home");的路径请问如何能无视\/的困扰呢?
    绝对路径拼接主要的困扰在2个地方,
    1. windows是\ linux 是/ ,当然File.separator可以自动获取,但我更喜欢都用"/".
    2.getRealPath("")获得路径有时候最后带个分割符,有时候不带,(似乎取决于服务器,tomcat和weblogic就不同)
    拼接时就会产生如"C:\Tomcat 5.5\webapps\expstudent\/cacerts.store"  这种情况,
    我想的办法是所有绝对路径都用String的replace 方法把\/ // 替换成/
    土办法啊,我实在没别的办法了。
      

  13.   

    你说的这个方法当然可以,只是移植性稍差一点,如果你的 web application 是以 WAR 包的方式部署的,这种方式就会有问题。
    我说的方法需要在系统部署的时候做一点额外的工作,这算是增加“可移植性”的代价吧。如果你用我程序中给出的方法来拼接出绝对路径,的确是不用关心分隔符的问题,你试试就知道了,最后总能得到一个正确的绝对路径字符串。
      

  14.   

    楼上太强了!用File 构造路径,的确不怕//  \/ 之类的问题了!
    多谢!你解决了困扰我很久的问题。