今天工作中多处用到了这个类,特此研究下他的具体用法,主要是加载配置文件,然后以key和value形式加载出来。
测试程序如下:
public static void main(String[] args)throws IOException {
try {
@SuppressWarnings("unused")
InputStream stream = Class.forName("com.lvmama.properties.PropertiesTest").getResourceAsStream("webService.properties");
Properties p=new Properties();
p.load(stream);
System.out.println(p.getProperty("TAIPING_SERVER"));
p.setProperty("2", "sdfsdf");
System.out.println(p.getProperty("2"));
} catch (ClassNotFoundException e){
// TODO Auto-generated catchblock
e.printStackTrace();
}
}
公司封装了一个工具类用来加载配置文件,类如下:
package com.lvmama.vst.insurant.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 配置管理对象
* @author clj 2009-9-12
*
*/
public class Configuration {
private static final Log log = LogFactory.getLog(Configuration.class);
private static Configuration configuration = null;
private Configuration() {
}
/**
* 得到配置对象
*
* @return
*/
public static Configuration getConfiguration() {
if (configuration == null) {
configuration=new Configuration();
}
return configuration;
}
/**
* 获取配置的资源文件
*
* @param resource
* @return
*/
public Properties getConfig(String resource) {
Properties config = new Properties();
try {
config.load(getResourceAsStream(resource));
} catch (IOException e) {
log.error("装载配置文件异常", e);
}
return config;
}
/**
* 获取配置的资源文件数据流
*
* @param resource
* @return
*/
public InputStream getResourceAsStream(String resource) {
String realSource = resource.startsWith("/") ? resource.substring(1) : resource;
return Thread.currentThread().getContextClassLoader().getResourceAsStream(realSource);
}
}
下面我们开始分析它的源码
先看load源码,进入Properties类
public synchronized void load(InputStream inStream)throws IOException {
load0(new LineReader(inStream));
}
执行实例化内部类LineReader
public LineReader(InputStreaminStream) {
this.inStream = inStream;
inByteBuf = new byte[8192];
}
然后执行该类的加载配置信息主方法;方法如下:
private void load0 (LineReaderlr) throws IOException {
char[] convtBuf = newchar[1024];
int limit;
int keyLen;
int valueStart;
char c;
boolean hasSep;
boolean precedingBackslash;
// readLine()方法开始调用LineReader的方法,主要加载配置文件中的数据信息
while ((limit = lr.readLine()) >=0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
//System.out.println("line=<"+ new String(lineBuf, 0, limit) + ">");
precedingBackslash = false;
while (keyLen < limit) {
c = lr.lineBuf[keyLen];
//need check if escaped.
if ((c == '=' || c == ':') && !precedingBackslash) {
valueStart = keyLen + 1;
hasSep = true;
break;
} else if ((c == '' || c == '\t' || c == '\f') && !precedingBackslash){
valueStart = keyLen + 1;
break;
}
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
keyLen++;
}
while (valueStart < limit){
c = lr.lineBuf[valueStart];
if (c != ' ' &&c != '\t' && c != '\f') {
if (!hasSep &&(c == '=' || c == ':')) {
hasSep = true;
} else {
break;
}
}
valueStart++;
}
String key = loadConvert(lr.lineBuf,0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf,valueStart, limit - valueStart, convtBuf);
put(key,value);
}
}
接下来看下这个LineReader类的readLine()方法
int inLimit= (inStream==null)?reader.read(inCharBuf)
:inStream.read(inByteBuf);
先读取一个数据放入inByteBuf
c = (char) (0xff & inByteBuf[inOff++]);//对得到的值进行转码
//跳过空格键
if (skipWhiteSpace){
if (c == ' ' || c == '\t' || c == '\f') { //判断是否空格,制表符换页符
continue; //如果是结束本次循环
}
if (!appendedLineBegin && (c == '\r' || c == '\n')) { //跳过换行符和回车符
continue;
}
skipWhiteSpace = false;
appendedLineBegin = false;
}
//以下判断是否新行,新行的话则给isCommentLine做个标准,跳出该循环
if (isNewLine) {
isNewLine = false;
if (c == '#' || c == '!') { //如果是“#”或“!”则跳过,即为注释行
isCommentLine = true;
continue;
}
}
//不是换行符和回车符,下面主要是当容量不足的时候,扩容
if (c != '\n' && c != '\r'){
lineBuf[len++] = c; //记录该字节
if (len == lineBuf.length) {
int newLength = lineBuf.length * 2;//扩容
if (newLength < 0) {
newLength = Integer.MAX_VALUE;
}
char[] buf = newchar[newLength];
System.arraycopy(lineBuf, 0,buf, 0, lineBuf.length);// lineBuf复制到buf
lineBuf = buf;
}
//flip the preceding backslash flag
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
}
else {
// reached EOL 下面为结束行,此行结束,
if (isCommentLine || len == 0) {
isCommentLine = false;
isNewLine = true; //下一次就为新行
skipWhiteSpace = true;
len = 0;
continue;
}
if (inOff >= inLimit) {
inLimit = (inStream==null)
?reader.read(inCharBuf)
:inStream.read(inByteBuf);
inOff = 0;
if (inLimit <= 0) {
return len;
}
}
if (precedingBackslash) {
len -= 1;
//skip the leading whitespacecharacters in following line
skipWhiteSpace = true;
appendedLineBegin = true;
precedingBackslash = false;
if (c == '\r') {
skipLF = true;
}
} else {
return len;
}
}