JDK源碼學習(9)- java.util.Properties實例與源碼

  1. java.util.Properties說明。

該類主要是讀取屬性配置文件,兩種文件類型:普通文件格式爲key = value;xml文件。

1)key = value示例如下:

public class TestProperties {

	public static void main(String[] args) {
		Properties properties = new Properties();
		FileInputStream fileInputStream;
		try {
			fileInputStream = new FileInputStream(new File("D:/testProperties.txt"));
//			properties.loadFromXML(fileInputStream);
			properties.load(fileInputStream);
			for (Object pro : properties.keySet()) {
				System.out.println(pro + "==" + properties.get(pro));
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

配置文件爲:

name = hello
value = good

結果爲:

name==hello
value==good

2)讀取xml文件,代碼如下:

public class TestProperties {

	public static void main(String[] args) {
		Properties properties = new Properties();
		FileInputStream fileInputStream;
		try {
			fileInputStream = new FileInputStream(new File("D:/testProperties.xml"));
			properties.loadFromXML(fileInputStream);
//			properties.load(fileInputStream);
			for (Object pro : properties.keySet()) {
				System.out.println(pro + "==" + properties.get(pro));
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

配置文件爲:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Hi</comment>
<entry key="foo">bar</entry>
<entry key="fu">baz</entry>
<entry key="feee">baeee</entry>
</properties>

運行結果爲:

feee==baeee
fu==baz
foo==bar

2.源碼分析:

該類繼承自HashTable,結構爲key-value,如下:

public class Properties extends Hashtable<Object,Object>

1)load(InputStream)方法,該方法主要作用是讀取配置文件內的相關配置,並且將信息用key-value結構存放到Properties中。源碼爲:

  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;
        //1.按行讀取配置文件,返回值爲該行的長度
        while ((limit = lr.readLine()) >= 0) {
            c = 0;
            keyLen = 0;
            valueStart = limit;
            hasSep = false;

            //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
            precedingBackslash = false;
            //1.1對該行每個字符進行遍歷,找到=或者:符號的位置
            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++;
            }
            //keyLen爲符號之前不爲空的最終位置,valueStart爲符號之後的第一個不爲空的位置
            String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
            String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
            //將解析出的key和value存放到hashTable中
            put(key, value);
        }
    }

2)store(OutputStream out, String comments)方法,out爲輸出的文檔,comments爲配置文件的說明,在key-value時爲註釋信息,在xml文件格式下爲<comments>標籤內容。源代碼如下:

 public void store(OutputStream out, String comments)
        throws IOException
    {
        store0(new BufferedWriter(new OutputStreamWriter(out, "8859_1")),
               comments,
               true);
    }

    private void store0(BufferedWriter bw, String comments, boolean escUnicode)
        throws IOException
    {
        if (comments != null) {
            writeComments(bw, comments);
        }
        bw.write("#" + new Date().toString());
        bw.newLine();
        synchronized (this) {
            for (Enumeration<?> e = keys(); e.hasMoreElements();) {
                String key = (String)e.nextElement();
                String val = (String)get(key);
                key = saveConvert(key, true, escUnicode);
                /* No need to escape embedded and trailing spaces for value, hence
                 * pass false to flag.
                 */
                val = saveConvert(val, false, escUnicode);
                bw.write(key + "=" + val);
                bw.newLine();
            }
        }
        bw.flush();
    }
    
    private static void writeComments(BufferedWriter bw, String comments)
        throws IOException {
        bw.write("#");
        int len = comments.length();
        int current = 0;
        int last = 0;
        char[] uu = new char[6];
        uu[0] = '\\';
        uu[1] = 'u';
        while (current < len) {
            char c = comments.charAt(current);
            if (c > '\u00ff' || c == '\n' || c == '\r') {
                if (last != current)
                    bw.write(comments.substring(last, current));
                if (c > '\u00ff') {
                    uu[2] = toHex((c >> 12) & 0xf);
                    uu[3] = toHex((c >>  8) & 0xf);
                    uu[4] = toHex((c >>  4) & 0xf);
                    uu[5] = toHex( c        & 0xf);
                    bw.write(new String(uu));
                } else {
                    bw.newLine();
                    if (c == '\r' &&
                        current != len - 1 &&
                        comments.charAt(current + 1) == '\n') {
                        current++;
                    }
                    if (current == len - 1 ||
                        (comments.charAt(current + 1) != '#' &&
                        comments.charAt(current + 1) != '!'))
                        bw.write("#");
                }
                last = current + 1;
            }
            current++;
        }
        if (last != current)
            bw.write(comments.substring(last, current));
        bw.newLine();
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章