properties使用
什麼是Properties?
Properties(Java.util.Properties),該類主要用於讀取Java的配置檔案,不同的程式語言有自己所支援的配置檔案,配置檔案中很多變數是經常改變的,為了方便使用者的配置,能讓使用者夠脫離程式本身去修改相關的變數設定。就像在Java中,其配置檔案常為.properties檔案,是以鍵值對的形式進行引數配置的。
Properties 詳解
properties結構
Api介紹
建構函式
建構函式 | 說明 |
---|---|
Properties() | 建立空的Properties |
Properties(Properties ps) | 基於已經存在的properties去建立 |
常用方法
方法 | 說明 |
---|---|
public synchronized void load(InputStream inStream) | 給予輸入流去載入Properties |
public synchronized void load(Reader reader) | 給予文字輸入流去載入Properties |
Object setProperty(String key, String value) | 設定屬性 |
public synchronized void load(InputStream inStream) | 給予輸入流去載入Properties |
public void store(Writer writer, String comments) | 儲存檔案 |
public String getProperty(String key) | 獲取properties key |
原始碼講解
load原始碼分析
指定從流中載入key/value屬性值,底層都是將流封裝成為LineReader物件,然後通過load0方法來載入屬性鍵值對的,載入完屬性後流物件是不會關閉的。這兩個方法對應的properties檔案格式如下:
class LineReader {
/**
* 根據位元組流建立LineReader物件
*
* @param inStream
* 屬性鍵值對對應的位元組流物件
*/
public LineReader(InputStream inStream) {
this.inStream = inStream;
inByteBuf = new byte[8192];
}
/**
* 根據字元流建立LineReader物件
*
* @param reader
* 屬性鍵值對對應的字元流物件
*/
public LineReader(Reader reader) {
this.reader = reader;
inCharBuf = new char[8192];
}
// 位元組流緩衝區, 大小為8192個位元組
byte[] inByteBuf;
// 字元流緩衝區,大小為8192個字元
char[] inCharBuf;
// 當前行資訊的緩衝區,大小為1024個字元
char[] lineBuf = new char[1024];
// 讀取一行資料時候的實際讀取大小
int inLimit = 0;
// 讀取的時候指向當前字元位置
int inOff = 0;
// 位元組流物件
InputStream inStream;
// 字元流物件
Reader reader;
/**
* 讀取一行,將行資訊儲存到{@link lineBuf}物件中,並返回實際的字元個數
*
* @return 實際讀取的字元個數
* @throws IOException
*/
int readLine() throws IOException {
// 總的字元長度
int len = 0;
// 當前字元
char c = 0;
boolean skipWhiteSpace = true;
boolean isCommentLine = false;
boolean isNewLine = true;
boolean appendedLineBegin = false;
boolean precedingBackslash = false;
boolean skipLF = false;
while (true) {
if (inOff >= inLimit) {
// 讀取一行資料,並返回這一行的實際讀取大小
inLimit = (inStream == null) ? reader.read(inCharBuf) : inStream.read(inByteBuf);
inOff = 0;
// 如果沒有讀取到資料,那麼就直接結束讀取操作
if (inLimit <= 0) {
// 如果當前長度為0或者是改行是註釋,那麼就返回-1。否則返回len的值。
if (len == 0 || isCommentLine) {
return -1;
}
return len;
}
}
// 判斷是根據字元流還是位元組流讀取當前字元
if (inStream != null) {
// The line below is equivalent to calling a ISO8859-1 decoder.
// 位元組流是根據ISO8859-1進行編碼的,所以在這裡進行解碼操作。
c = (char) (0xff & inByteBuf[inOff++]);
} else {
c = inCharBuf[inOff++];
}
// 如果前一個字元是換行符號,那麼判斷當前字元是否也是換行符號
if (skipLF) {
skipLF = false;
if (c == '\n') {
continue;
}
}
// 如果前一個字元是空格,那麼判斷當前字元是不是空格類字元
if (skipWhiteSpace) {
if (c == ' ' || c == '\t' || c == '\f') {
continue;
}
if (!appendedLineBegin && (c == '\r' || c == '\n')) {
continue;
}
skipWhiteSpace = false;
appendedLineBegin = false;
}
// 如果當前新的一行,那麼進入該if判斷中
if (isNewLine) {
isNewLine = false;
// 如果當前字元是#或者是!,那麼表示該行是一個註釋行
if (c == '#' || c == '!') {
isCommentLine = true;
continue;
}
}
// 根據當前字元是不是換行符號進行判斷操作
if (c != '\n' && c != '\r') {
// 當前字元不是換行符號
lineBuf[len++] = c;// 將當前字元寫入到行資訊緩衝區中,並將len自增加1.
// 如果len的長度大於行資訊緩衝區的大小,那麼對lineBuf進行擴容,擴容大小為原來的兩倍,最大為Integer.MAX_VALUE
if (len == lineBuf.length) {
int newLength = lineBuf.length * 2;
if (newLength < 0) {
newLength = Integer.MAX_VALUE;
}
char[] buf = new char[newLength];
System.arraycopy(lineBuf, 0, buf, 0, lineBuf.length);
lineBuf = buf;
}
// 是否是轉義字元
// flip the preceding backslash flag
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
} else {
// reached EOL
if (isCommentLine || len == 0) {
// 如果這一行是註釋行,或者是當前長度為0,那麼進行clean操作。
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.
len -= 1;
// skip the leading whitespace characters in following line
skipWhiteSpace = true;
appendedLineBegin = true;
precedingBackslash = false;
if (c == '\r') {
skipLF = true;
}
} else {
return len;
}
}
}
}
}
store原始碼分析
private void store0(BufferedWriter bw, String comments, boolean escUnicode) throws IOException {
2 if (comments != null) {
3 // 寫出註釋, 如果是中文註釋,那麼轉化成為8859-1的字元
4 writeComments(bw, comments);
5 }
6 // 寫出時間註釋
7 bw.write("#" + new Date().toString());
8 // 新起一行
9 bw.newLine();
10 // 進行執行緒間同步的併發控制
11 synchronized (this) {
12 for (Enumeration e = keys(); e.hasMoreElements();) {
13 String key = (String) e.nextElement();
14 String val = (String) get(key);
15 // 針對空格進行轉義,並根據是否需要進行8859-1編碼
16 key = saveConvert(key, true, escUnicode);
17 /*
18 * No need to escape embedded and trailing spaces for value,
19 * hence pass false to flag.
20 */
21 // value不對空格進行轉義
22 val = saveConvert(val, false, escUnicode);
23 // 寫出key/value鍵值對
24 bw.write(key + "=" + val);
25 bw.newLine();
26 }
27 }
28 bw.flush();
29 }
properties實戰
實現讀取ex1.properties檔案寫入另外一個檔案ex2.properties
- 準備檔案test.properties
#bbaba
#Mon Jun 07 11:38:21 CST 2021
hah=ceshi
- 開始拷貝
Properties properties = new Properties();
properties.load(new FileReader(new File("test.properties")));
System.out.println(properties.get("hah"));
properties.store(new FileWriter(new File("test2.properties")),"ceshi2");
- 控制檯輸出
ceshi
Process finished with exit code 0
此時classpath下可以檢視到新建的test2.properties檔案。
結束
識別下方二維碼!回覆:
入群
,掃碼加入我們交流群!
點贊是認可,在看是支援