Scenario:
Configuration file config.properties
configuration item cfg.regexp=\d+\t
Load configuration file code
InputStream ins = PropManager.class.getResourceAsStream("/config.properties");
prop.load(ins);
Phenomenon:
print cfg. The value of regexp is output as "d+ ", not the expected "\d+\t"
Reason:
After reading the code, I found that the Properties class has escaped '\', and only handles '\uxxxx', '\t ','\n','\r','\f' In other cases, simply swallow the '\'
1 while (off < end) {
2 aChar = in[off++];
3 if (aChar == '\\') {
4 aChar = in[off++];
5 if(aChar == 'u') {
6 // Read the xxxx
7 int value=0;
8 for (int i=0; i<4; i++) {
9 aChar = in[off++];
10 switch (aChar) {
11 case '0': case '1': case '2': case '3': case '4':
12 case '5': case '6': case '7': case '8': case '9':
13 value = (value << 4) + aChar - '0';
14 break;
15 case 'a': case 'b': case 'c':
16 case 'd': case 'e': case 'f':
17 value = (value << 4) + 10 + aChar - 'a';
18 break;
19 case 'A': case 'B': case 'C':
20 case 'D': case 'E': case 'F':
21 value = (value << 4) + 10 + aChar - 'A';
22 break;
23 default:
24 throw new IllegalArgumentException(
25 "Malformed \\uxxxx encoding.");
26 }
27 }
28 out[outLen++] = ( char )value;
29 } else {
30 if (aChar == 't') aChar = '\t' ;
31 else if (aChar == 'r') aChar = '\r' ;
32 else if (aChar == 'n') aChar = '\n' ;
33 else if (aChar == 'f') aChar = '\f' ;
34 out[outLen++] = aChar;
out[outLen++] = (char)aChar;
38 }
39 }
Solution:
My solution is to write a simple parsing
convention myself
- The first occurrence of '=' in each line is used as a separator (Properties class can support key:value format)
- Both key and value ignore leading and trailing whitespace characters
- Do not escape strings
1 while((line = buffReader.readLine())!=null){
2 line = line.trim();
3 if(line.startsWith("#") || line.equals("")){// 忽略#开头的注释
4 continue;
5 }
6
7 int index = line.indexOf('=');
8 if(index <= 0){
9 logger.error("********错误的配置文件格式!********line = " + line);
10 continue;
11 }
12 String key = line.substring(0, index).trim();
13 String value = (index+1>=line.length()) ? "":line.substring(index+1).trim();// 避免越界
14 prop.put(key, value);
15 }
之所以把它记下来是因为我跟同事说起这个现象的时候,同事发现他之前写的代码用过类似的正则表达式配置方式,正则表达式里面希望匹配绝对的'\.',而经过Properties类转义之后变成了'.',意义就变成了“任意字符”,由于运行并不报错,而且某系情况下结果还是正确的,于是一个潜在的bug就出现了