1. 程式人生 > >Java Properties類載入配置檔案轉義問題

Java Properties類載入配置檔案轉義問題

場景:
配置檔案config.properties
配置項cfg.regexp=\d+\t
載入配置檔案程式碼
InputStream ins = PropManager.class.getResourceAsStream("/config.properties");
prop.load(ins);

現象:
列印cfg.regexp的值輸出為"d+ ",而不是期望的"\d+\t"

原因:
看了下程式碼,發現Properties類對'\'做了轉義處理,而且只處理'\uxxxx', '\t','\n','\r','\f'這幾種情況,對於其他情況,就簡單的把'\'吞掉了

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++] = (char)aChar;
}
}

解決方法:
我的解決方法是,自己寫個簡單的解析
約定
[list]
[*]每行第一次出現的'='作為分割符(Properties類可以支援key:value格式)
[*]key和value都忽略前後空白字元
[*]不對字串做轉義處理
[/list]


while((line = buffReader.readLine())!=null){
line = line.trim();
if(line.startsWith("#") || line.equals("")){// 忽略#開頭的註釋
continue;
}

int index = line.indexOf('=');
if(index <= 0){
logger.error("********錯誤的配置檔案格式!********line = " + line);
continue;
}
String key = line.substring(0, index).trim();
String value = (index+1>=line.length()) ? "":line.substring(index+1).trim();// 避免越界
prop.put(key, value);
}


之所以把它記下來是因為我跟同事說起這個現象的時候,同事發現他之前寫的程式碼用過類似的正則表示式配置方式,正則表示式裡面希望匹配絕對的'\.',而經過Properties類轉義之後變成了'.',意義就變成了“任意字元”,由於執行並不報錯,而且某系情況下結果還是正確的,於是一個潛在的bug就出現了