找到eclipse保存java工程使用的workspace文件夹。
打开一个java工程,这里打开的是Heima工程,会发现里面有一些目录和文件。
其中有一个.classpath文件。那么.classpath是干嘛用的呢?里面写的是什么东西?
用计算本打开来看:
看不懂是什么意思。。网上找了一些资料:
<!-- 源码目录 -->
<classpathentry kind="src" path="src"/>
<!-- JDK运行时容器 -->
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<!-- 以下为类库 path为你自定义的目录 -->
<classpathentry kind="lib" path="lib/swing-layout-1.0.3.jar"/>
<!-- 编译后输出class 目录 -->
<classpathentry kind="output" path="bin"/>
原来如此:src目录是存放源代码的目录,而bin是存放class字节码文件的目录。
----------------------
我把.classpath文件给修改一下:
把<classpathentry kind="output" path="bin"/> 中的path改为“bi”
修改.classpath文件修改后重启eclipse
运行:CopyText.java
运行后:错误: 找不到或无法加载主类 day18.CopyText
解决办法:看完以下分析,只要把原来bin目录下day18目录拷贝到bi文件夹下就可以了。
------------------
修改.classpath文件之后,重启eclipse,在工程的src下新建一个black包
会看到工程目录下新多了一个文件夹bi,而bi文件夹下又出现一个black的文件夹
black文件夹下是空的。。
--------------------
现在在eclipse里的Heima工程black包里新建立一个Test.java
public class Test {
public static void main(String[] args) {
System.out.println("hello");
}
}
然后保存,会发现black文件夹下生成了Test.class文件
---------------
在eclipse里编译运行Test.java程序输出:
---------------
在black文件夹下新建一个eula.txt文件,使用类加载器加载
Test.class.getClassLoader().getResourceAsStream("black/eula.txt");
InputStream is = Test.class.getResourceAsStream("eula.txt");
FileWriter fw = new FileWriter("mm.txt");
int ch = 0;
while((ch=is.read())!=-1){
fw.write(ch);
fw.flush();
}
最后在Heima的工程下生成了一个mm.txt文件。
因此可知IO流的相路径是工程。
类加载器相对加载路径是.classpath里指定的存放class字节码文件的目录。
在myeclipse的.classpath中指定的存放class字节码文件的目录是WebRoot/WEB-INF/classes
<classpathentry kind="output" path="WebRoot/WEB-INF/classes"/>
所以在myeclipse中使用类加载器加载文件的时候,也会相对去WebRoot/WEB-INF/classes目录下加载。
-------------------在Eclipse里设置Build Path
Window->Preferences->Java->Build Path
在eclipse里设置存放源代码的目录和存放class字节码文件的目录。新建一个工程,那个工程就开始生效,并且那个工程的.classpath文件也是对应的。
------------------------------
应用:采用配置文件加反射的方式创建HashSet的实例对象,观察运行结果。
配置文件config.properties的内容是:
className=java.util.HashSet
1、使用传统IO流读取配置文件
import java.io.*;
import java.util.*;
public class PropsLoad {
public static void main(String[] args) throws Exception {
InputStream ips = new FileInputStream("config.properties");//IO流读取配置文件
Properties props = new Properties();
props.load(ips);
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();//反射
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
}
}
在eclipse里,如果把 config.properties文件放在和PropsLoad.java同一个包里的话或者src目录下,运行:
Exception in thread "main" java.io.FileNotFoundException: config.properties (系统找不到指定的文件。)
那么怎么放置才可以呢?
对于IO流来说,使用相对路径,直接写“config.properties”路径的话,config.properties文件要放在你的工程目录下。
2、使用类加载器加载配置文件。
现在把config.properties文件放在了工程目录下
import java.io.*;
import java.util.Collection;
import java.util.Properties;
public class ClassLoad {
public static void main(String[] args) throws Exception {
InputStream ips= ClassLoad.class.getClassLoader().getResourceAsStream("config.properties");//使用类加载器进行加载资源文件
Properties props = new Properties();
props.load(ips);
ips.close();
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
//Collection collections = new HashSet();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
}
}
运行结果: Exception in thread "main" java.lang.NullPointerException
出现空指针异常,因为ips引用为null,说明类加载器没有找到配置文件,提供的路径不正确或者说是config.properties文件存放的路径不对。
----------------
那么现在就要知道类加载器加载文件默认相对于哪个目录呢?
这时候就要看eclipse下,这个工程的.classpath文件了。
看到这个.classpath文件中 <classpathentry kind="output" path="bin"/>
就知道了,类加载器加载文件默认相对于bin这个目录。因此要把 config.properties文件存放在bin目录下。再次运行就OK了。
【类加载器去找class文件存放的路径(bin目录下存放class文件,bin就是.classpath文件设置好的)】
------------------
另外Class类的API里也提供了InputStream getResourceAsStream(String name)方法。
用某个类去加载,而不是类加载器,其实内部还是调用的getClassLoader
那么就可以这样写来加载资源文件了:
InputStream ips= ClassLoad.class.getResourceAsStream("config.properties");
使用类加载有什么好处呢?
这个Class类提供的这个getResourceAsStream方法很爽的,只需要把配置文件和源程序放在同一包里面就可以了。
如果在eclipse下开发,就把配置文件放在src目录或者src的某个子目录包下面,它会自动拷贝到bin目录或者bin目录与src目录对应的子目录下面去。
(bin目录和src目录是对应的)
------------
用某个类去加载,既可以用相对路径,还可以用绝对路径。只要打斜杠“/”就不是相对的了,而是相对于classpath的根(classpath的根就是bin,/就代表bin)。
ClassLoad.java是在cn.itcast.enhance包下面的源程序。并且config.properties和ClassLoad.java在同一个包里
这时候使用绝对路径想要成功加载的话。就要从根“/”开始写上完整的路径:
InputStream ips= ClassLoad.class.getResourceAsStream("/cn/itcas/enhance/config.properties");
如果资源文件和我的包有关系,我就用相对的路径。如果和我的包没关系,就用绝对的路径。
不管是相对还是绝对,内部调用的都是getClassLoader。