在普通的Java类中,如果需要获取一个文件,可以通过字节码文件获取,也可以通过类加载器获取,通过字节码文件Class对象获取文件可以有两种方式,一种是获取到一个文件的输入流,然后以流的方式来操作该文件,一种是获取该文件的路径,然后通过File对象来操作该文件,通过类加载器来获取文件跟字节码文件对象获取文件是一样的,只不过他们两种方式相对的路径不一样,字节码文件对象获取文件时是相对于自身的路径而言的,而类加载器获取文件时是相对于类路径而言的:
一、假如我要在Test.java中获取类路径(classes文件夹)下的db.properties文件,这时候可以考虑用类加载器来获取,因为类加载器获取文件的路径默认是类路径下:
================================类加载器获取==============================
1.获取文件的流再通过Properties对象来操作properties文件:
InputStream in = Test.class.getClassLoader().getResourceAsStream("db.properties");
Properties props = new Properties();
props.load(in);
String name = props.getProperty("name");
System.out.println(name);
2.获取文件的路径再通过File对象操作文件:
String path = Test.class.getClassLoader().getResource("db.properties").getPath();
File file = new File(path);
一、假如我要在Test.java中获取跟Test.java文件在相同路径下的db.properties文件,这时候可以考虑用字节码文件对象来获取,因为字节码文件对象获取文件的路径默认是它自己所在的路径下:
1.获取文件路径再通过File对象操作文件:
String path = Test.class.getResource("db.properties").getPath();
System.out.println("path:"+path);
File file = new File(path);
System.out.println("file.getPath():"+file.getPath());
2.获取文件的流:
InputStream in = Test.class.getResourceAsStream("db.properties");
Properties props = new Properties();
props.load(in);
String name = props.getProperty("name");
System.out.println(name);
三、知识补充:
加入我要获取的文件在Test.java文件所在目录的下一级目录呢?怎么获取?如图所示:
答:加入Test.java在cn.itcast.servlet目录下,而你要获取的db.properties文件在cn.itcast.servlet.resource文件夹下,这种情况,你可以这么获取:
1.通过字节码文件对象获取:
获取方式跟上面的字节码文件对象获取文件的方式一样,但是getResource()或getResourceAsStream()方法里面,要写成"resource/db.properties"
2.通过类加载器获取:
获取方式跟上面的类加载器获取的方式一样,但是getResource()或getResourceAsStream()方法里面,要写成"cn/itcast/servlet/resource/db.properties"
下面是用Java实现了js中的eval函数的简单功能,打印一句话 "Hello ***":
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class JavaCompilerTest {
/*
从java6版本开始,已经支持动态编译了,你可以在运行期直接编译.java文件,执行.class文件,并且能够获得相关的输入输出,
甚至还能监听相关的事件。
java的动态编译提供了多种渠道,比如,可以动态编译一个字符串,也可以是文本文件,也可以是编译过的字节码文件(.class文件),
甚至可以是存放在数据库中的明文代码或字节码,只要是符合java规范的就都可以在运行期动态加载,其实现方式就是实现JavaFileObject
接口,重写getCharContent、openInputStream、openOutputStream,或者实现JDK
已经提供的两个SimpleJavaFileObject、ForwardingJavaFileObject。下面我演示一下,如何动态编译一个字符串
*/
/**
* Java动态编译演示
*/
public static void main(String[] args) throws Exception {
//Java源代码
String sourceStr = "public class Hello{public String sayHello(String name){return \"Hello,\"+name;}}";
//类及文件名
String clsName = "Hello";
//方法名
String methodName = "sayHello";
/**
* 当前编译器:注意,如果是用的jdk1.6的版本(建议使用jdk1.7,1.7是没有任何问题的),ToolProvider.getSystemJavaCompiler()拿到的对象将会为null,
* 原因是需要加载的Tools.jar不在jdk安装目录的jre目录下,需要手动将lib目录下的该jar包拷贝到jre下去,详情请参考:
*
*/
JavaCompiler cmp = ToolProvider.getSystemJavaCompiler();
//Java标准文件管理器
StandardJavaFileManager fm = cmp.getStandardFileManager(null, null, null);
//Java文件对象
JavaFileObject jfo = new StringJavaObject(clsName, sourceStr);
//编译参数,类似于javac <options> 中的options
List<String> optionsList = new ArrayList<String>();
//编译文件的存放地方,注意:此处是为Eclipse工具特设的
optionsList.addAll(Arrays.asList(new String[]{"-d", "./bin"}));
//要编译的单元
List<JavaFileObject> jfos = Arrays.asList(new JavaFileObject[]{jfo});
//设置编译环境
JavaCompiler.CompilationTask task = cmp.getTask(null, fm, null, optionsList, null, jfos);
//编译成功
if(task.call()){
//生成对象
Object obj = Class.forName(clsName).newInstance();
Class<? extends Object> cls = obj.getClass();
//调用sayHello方法
Method m = cls.getMethod(methodName, String.class);
String str = (String) m.invoke(obj, "royise");
System.out.println(str);
}
}
}
class StringJavaObject extends SimpleJavaFileObject {
/**
* 源代码
*/
private String content = "";
/**
* 遵循Java规范的类名及文件
*/
public StringJavaObject(String javaFileName, String content){
super(_createStringJavaObjectUri(javaFileName), Kind.SOURCE);
this.content = content;
}
/**
* 产生一个URL资源路径
*/
private static URI _createStringJavaObjectUri(String javaFileName) {
//注意此处未设置包名
return URI.create("String:///" + javaFileName + Kind.SOURCE.extension);
}
/**
* 文本文件代码
*/
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors)
throws IOException {
return content;
}
}