1.概述
1.本章主要是解析Properties(java.util.Properties)的介绍
2.在jdk源码中的位置如下
2.类的定义
1.public class Properties extends Hashtable<Object,Object>
2.Properties类继承自HashTable,本质是一个哈希类,
3.重要方法说明
3.1.load(InputStream inStream)
代码地址
https://gitee.com/gaoxinfu_admin/demo-jdk/tree/master/demo-jdk-properties
3.1.1.定义
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
3.1.2.使用样例说明
结构
package com.gaoxinfu.demo.jdk.demojdkproperties;
import org.junit.Test;
import java.io.*;
import java.util.Properties;
public class PropertiesDemo {
@Test
public void loadConfigProperties() throws FileNotFoundException, IOException {
String propertyFileName="/application.properties";
//使用getResourceAsStream 获取resouces文件夹下面的属性配置
InputStream is = this.getClass().getResourceAsStream(propertyFileName);
Properties props = new Properties();
props.load(is);
System.out.println(props.toString());
}
}
输出:
3.1.3源码说明
public synchronized void load(InputStream inStream) throws IOException {
//1.new LineReader(inStream) 初始构造一个读取属性文件的8M大小的byte[]数组
//2.load0方法调用
load0(new LineReader(inStream));
}
//我们在Properties文件中的配置,等号前面是key,等号后面value
private void load0 (LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
int limit;
int keyLen; //Properties文件中key值的lenth长度
int valueStart; //Properties文件中value值的开始的位置
char c;
boolean hasSep;
boolean precedingBackslash;
//1.limit=lr.readLine 读取一行数据,limit获取数据的字节大小(也是行尾的位置)
while ((limit = lr.readLine()) >= 0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
/**
*开始寻找key值结束位置
*System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
*标示 precedingBackslash反斜线符号,默认不是,
*主要是对于某些用户针对Properties文件中配置全部都写在一行,然后反斜杠区分不同的key
*/
precedingBackslash = false;
while (keyLen < limit) {
//该行标示 key的最后一个字符
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;
}
//一个一个字符往前移动知道知道=号或者:号,然后获取到key
keyLen++;
}
/**
*
*开始寻找value值开始位置
*/
while (valueStart < limit) {
c = lr.lineBuf[valueStart];
if (c != ' ' && c != '\t' && c != '\f') {
if (!hasSep && (c == '=' || c == ':')) {
hasSep = true;
} else {
break;
}
}
valueStart++;
}
/**
*获取key的值
*/
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
/**
*获取value的值
*loadConvert 方法介绍如下
*/
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
}
/**
* in 原始的一行数据
* off 开始位置
* len 长度
* convtBuf 初始化的字符数组长度1024
*
*/
private String loadConvert (char[] in, int off, int len, char[] convtBuf) {
/**
* 为了防止我们获取的数据的长度len大于初始化的convtBuf1024 我们这里做了一下判断
*/
if (convtBuf.length < len) {
int newLen = len * 2;
if (newLen < 0) {
newLen = Integer.MAX_VALUE;
}
convtBuf = new char[newLen];
}
char aChar;
char[] out = convtBuf;
int outLen = 0;
int end = off + len;
while (off < end) {
aChar = in[off++];
if (aChar == '\\') {
aChar = in[off++];
if(aChar == 'u') {
// Read the xxxx
int value=0;
for (int i=0; i<4; i++) {
aChar = in[off++];
switch (aChar) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
value = (value << 4) + aChar - '0';
break;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
value = (value << 4) + 10 + aChar - 'a';
break;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
value = (value << 4) + 10 + aChar - 'A';
break;
default:
throw new IllegalArgumentException(
"Malformed \\uxxxx encoding.");
}
}
out[outLen++] = (char)value;
} else {
if (aChar == 't') aChar = '\t';
else if (aChar == 'r') aChar = '\r';
else if (aChar == 'n') aChar = '\n';
else if (aChar == 'f') aChar = '\f';
out[outLen++] = aChar;
}
} else {
out[outLen++] = aChar;
}
}
return new String (out, 0, outLen);
}