Properties文件大家都用过,然而里面的思维我们有没有get到呢?和阿福一起看看吧!
我亲爱的Properties文件
我们在写代码的过程中经常在程序中需要用到一些值,对于这些值的管理的方法也是千奇百怪。那么,到底有哪些方法呢?下面,我们就来一起看看。
方法脑暴
首先,我们最常想到的就是将其写入到程序中去,我们往往会在代码中新建一个常量类,还会美其名曰”Constant”;见名知意,常量我们都会放在这个里面,但是,需要修改怎么办?怎么办?
这时候,我们可以祭出我们java学院派的IO系统,我们可以存储到文件系统中去。在需要的时候读取出来啊,这个想法简直是太美妙了。这里我都想到了,用“key,value”这种类似的格式进行存储,甚至用BufferedWriter和BufferedReader可以一行一行的存,一行一行的读,读出来后首先截断放到一个hashmap中去,至于为何要放到hashmap中去,这个没啥讲究啦!
然而,好操心啊!还需要我们编写额外的代码,当然我要是任性直接存入数据库也行啊!但是你不得访问数据库啊!幸运的是,java为我们提供了一种优雅的方法,那就是Properties文件。
Properties文件用法
protertis文件的用法到底是怎样的呢?首先,第一步,你得有protertis文件呀,其实在项目的classpath创建其即可。名字随便起,这个见名知意即可。有了文件,我们得先来看看文件内部的存储格式是怎样的?
# test
methodName=marryWm
我们可以看到,是以key-value形式存储的,而且中间以等号将两边分割开来,好吧,看到这里,突然感觉与我上面提到的方法好像啊,难道,JDK的作者竟然和我有一样想法,事实是怎样的呢,我们去看看!
在探究之前先放出到底如何使用的代码吧!
prop = new Properties();
InputStream in = FileService.class.getClassLoader().getResourceAsStream("urlutil.Properties");
try {
prop.load(in);
} catch (IOException e) {
e.printStackTrace();
}
String urlString = prop.getProperty(methodName);
有了这段代码,得到key对应的value是没有任何问题了,但是,刚才已经想着去探究了,那只能一探到底喽!
Proterties类实现原理
首先进入Proterties类的源代码:
public class Properties extends Hashtable<Object,Object>
竟然继承了HashTable,看来我们的猜测方向没错。可是我们该从哪里看起呢?我们当然是从其如何加载文件到内存中和我们程序中看起,这个就是我们的切入点!下面来看load方法。
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
private void load0 (LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
int limit;
int keyLen;
int valueStart;
char c;
boolean hasSep;
boolean precedingBackslash;
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);
}
}
上面的这一段代码看上去显得好复杂啊,我们不想要看懂,只是看到它使用了inStream构造了内部类LineReader,最后在一个可爱的while循环里将值put到了自身也就是一个HashTable中去,至此,我们就可以getProperty()方法拿到我们需要的东西了,其实,getProperty()方法只是对get()方法在次做了封装,为的就是更加直观啊,你说对吧!看代码:
public String getProperty(String key) {
Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}
总结
今天我们本来只是想搞定一下proterties文件的用法的,结果发现了Proterties类的作者和我们的想法竟然不谋而合。基于这样的想法,我们还可以构造出属于自己的配置文件读取类,当然,如果你确实有那样的需求,尽管去折腾。
看来,多折腾才是王道!今天对protertis文件的分享就到这里了。