遇到过很多人,甚至工作了几年的人,经常搞不清classpath,写了一个小程序, Eclipse能运行的程序,在DOS下就经常运行不了了,一般都是报这样的异常:java.lang.ClassNotFoundException。群里一旦有人问起,一帮人看都不看,一般都由以下几种说法:
1. 设置了环境变量没? 这种几率还真小, 安装了jdk基本上毫无疑问都会设置环境变量.
2. java文件的问题. 这个完全就是在胡扯了
3. 先把java文件编译一下. 这个都在eclipse能运行了. 已经都编译好了,无需再多此一举。
4. classpath路径有问题. 这个还真要稍微注意一下. 如果是jdk5.0及以后的版本, 那么classpath是完全可以不用设置的.
现在大部分人应该都不会再使用jdk1.4或者更老的版本了吧. 所以这个概率也很小.
5. 把环境变量重新设置一下. 这个???
6. 这个问题太多了,百度去吧. 我想这么说的人估计自己也搞不清楚。很多人都习惯了Eclipse,怎么在DOS下编译和运行还真不熟悉.
首先说明一下, 上面的程序是带有包名的, 很好解决, 只要进入到项目的bin目录下, 运行java 报名.类名 即可.
下面的程序稍微有点区别.也涉及到相对路径的问题. 项目结构如下:
IDEAndDosTest.java的代码如下(不要去揪程序的规范):
public static void main(String[] args) throws IOException { FileInputStream in = new FileInputStream("src/iotest/test.txt"); int data; while((data = in.read()) != -1) { System.out.print(data + " "); } in.close(); }
很简单, 就是读取一个文件, 打印字节.
在Eclipse下运行当然是没有任何问题的.
在DOS下运行,进入到的目录是bin. 这时候运行发现, 报异常了:
Exception in thread "main" java.io.FileNotFoundException: src\iotest\test.txt ( 系统找不到指定的路径。)
异常也很明显, 文件路径不对, 没错, 路径当然不对了. 既然现在在bin目录下, 那么肯定相对应bin目录了.
这时需要搞清楚的就是两个系统属性"user.dir"和"java.class.path".
GetClassPathAndUserDir类的代码很简单:
System.out.println(System.getProperty("user.dir")); System.out.println(System.getProperty("java.class.path"));
在Eclipse下运行, 结果是:
user.dir = 磁盘路径\Test java.class.path = 磁盘路径\Test\bin
在DOS下运行(目录是bin), 结果是:
user.dir = 磁盘路径\Test\bin java.class.path = . // 其实就是磁盘路径\Test\bin
从以上的结果其实已经可以看出结果了。问题主要集中在"user.dir".
其实解决上面的问题也很简单. 换种方式, DOS下进入项目的目录, 也就是现在在Test目录下. 运行
java -cp bin iotest.IDEAndDosTest
OK. 没有任何问题.
其实这个时候user.dir已经发生了变化. 其实GetClassPathAndUserDir这个类在不同的目录下运行结果是有些差异的
比如,现在在Test目录下运行,结果是:
user.dir = 磁盘路径\Test java.class.path = bin
来个更好玩的, 直接在E盘下 运行,结果是:
user.dir = E:\ java.classpath = E:\Java\workspace\framework_workspace\Test\bin
可以发现java.classpath是不变的, 而user.dir是不断变化的.
不过要是在E盘下运行IDEAndDosTest,一样还是会报java.io.FileNotFoundException
从上面的结果也可以看出了"user.dir", 可以简单的说就是当前用户的目录.
把IDEAndDosTest.java稍作修改:
FileInputStream in = new FileInputStream("iotest/test.txt");
这个时候在DOS下(bin目录), 运行时没有任何的, 在Eclipse运行会报 java.io.FileNotFoundException
不过只要我们稍作修改就能让其运行正常:
做如下的修改运行也就完全没问题了.
既然这两种方式都这么麻烦, 那有没有什么好的替换方式呢 ?当然有了:
InputStream in = IDETest.class.getResourceAsStream("test.txt"); // 当前类的同目录下
或者
InputStream in = IDEAndDosTest.class.getClassLoader().getResourceAsStream("iotest/test.txt"); // classpath目录
现在不管你怎么运行, 都没有问题了(当然了你要指定好classpath)
其实也可以看出了如果要用绝对路径, 千万别涉及到"user.dir"的问题, 最好相对于你的classpath而言。