收藏自:http://www.blogjava.net/xmatthew/archive/2008/04/13/192534.html
针对于JDK本身提供的Properties类,增加了以下功能:
* 提供指定文件的读写编码支持 Properties使用的编码与当前操作系统有关。一般为 unicode
* 支持Properties变量的使用。如果 a=123 \n b=${a}456
* 当文件修改时,自动重新读取。
下面我把源代码粘于下面,供大家交流与学习之用,如有什么问题也希望大家能回复我。
使用方法:
a util tool which inpackaged Properties class just for easy to use. notice
that default Properties while loading from file which encodes by which you
specified. it provide a more convient way to use language encoding.
new feature: 1. add variable support. variable's format look like as ${}
notice that variable is only kown as it defined above it.
for example:
v1=abc
v2=ccc
v3=${v1} #here v3's value is abc
v4=${v3} #here v4's value is blank instead of ddd
v5=ddd
demo for the feature:
now we have a properties file the content as bellow:
firstname=Matthew
lastname=Xie
age=26
gender=male
fullname=${firstname}.${lastname}
city=bei jing
address=${city} fengtai
city_cn=丰台
here's our demo source code to show how to use this class.
String myTestPath = "test.ini";
SimpleIniUtil simpleIniUtil = null;
simpleIniUtil = new SimpleIniUtil();
// set the reload enabled. default is false.
// if setted true, after iniFile changed then when read the properties values it will reload it.
simpleIniUtil.setReloadOnchange(true);
try {
//with default encoding open properties file
simpleIniUtil.loadFile(myTestPath);
//with specified encoding open properties file
//and if the specified encoding not found it will throw a exception
simpleIniUtil.loadFile(myTestPath, "GB2312");
//here we print out all the properties
System.out.println(simpleIniUtil.toString());
//the print out result would like as follow:
Properties values{fullname=Matthew.Xie,address=bei jing fengtai,
age=26,gender=male,lastname=Xie,firstname=Matthew,city=bei jing,}
//get string properties of address
String address = simpleIniUtil.getPropertiesValue("address");
//get string properties of address
// with default value "beijing" if the properties name not found
address = simpleIniUtil.getPropertiesValue("address", "beijing");
//get integer properties of age
// with defaut value 26 if the properties name not found
int age = simpleIniUtil.getPropertiesInteger("age", 26);
//set string value and return the previous value of the specified key
in this property list, or null if it did not have one.
Object retObj = simpleIniUtil.setPropertiseValue(lastname, "hello");
if (retObj != null) {
String oldLastName = (String) retObj;
}
////store the properties file
//store to the opened file
simpleIniUtil.store();
//store to the specified file
simpleIniUtil.store("/home/test/another.ini");
//store to the specified file with comment
simpleIniUtil.store("/home/test/another.ini", "Matt update it");
/*
//the result should be as follow
#Matt update it
#update time:2006-05-24 11:19:00
age=
* /
} catch (IOException e) {
// here we should deal the exception
}
Author:
Matthew Xie
Since:
2006-01-08
源代码:
1
2 import java.io.BufferedReader;
3 import java.io.BufferedWriter;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileWriter;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.io.Serializable;
11 import java.text.DateFormat;
12 import java.text.SimpleDateFormat;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.Iterator;
16 import java.util.LinkedHashMap;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21
22 import org.apache.commons.lang.StringUtils;
23 import org.apache.log4j.Logger;
24
25
26 public class SimpleIniUtil implements Serializable {
27
28 /*
29 * log for this class
30 */
31 private static final Logger LOGGER = Logger.getLogger(SimpleIniUtil.class);
32
33 /* serail version uid */
34 private static final long serialVersionUID = 4841183980762719179L;
35
36 private String iniFile = null;
37
38 private Map<String, String> propContent;
39
40 private String defaultEncode = "GBK";
41
42 private boolean isReloadOnchange = false;
43
44 private long fileTime;
45
46 /**
47 * default constructor method
48 */
49 public SimpleIniUtil() {
50 propContent = new LinkedHashMap<String, String>();
51 }
52
53 /**
54 * set the load file encode
55 * @param encode
56 */
57 public void setEncode(String encode) {
58 this.defaultEncode = encode;
59 }
60
61 /**
62 * constructor method
63 * @param iniFile full properties file path
64 */
65 public SimpleIniUtil(String iniFile) {
66 this();
67 this.setIniFile(iniFile);
68 }
69
70 /**
71 * get the full properties file path
72 * @return file path
73 */
74 public String getIniFile() {
75 return iniFile;
76 }
77
78 /**
79 * set the properties file path
80 * @param iniFile full properties file path
81 */
82 public void setIniFile(String iniFile) {
83 this.iniFile = iniFile;
84 }
85
86 /**
87 * load the properties content from the file
88 * @return properteis content from the file
89 * @throws IOException IO about exception will throw out
90 */
91 public Map<String, String> loadFile() throws IOException {
92 return this.loadFile(this.iniFile);
93 }
94
95
96 /**
97 * load the propeties file by specified file path
98 * @param iniFile full file path
99 * @return properteis content from the file
100 * @throws IOException IO about exception will throw out
101 */
102 public Map<String, String> loadFile(String iniFile) throws IOException {
103 return this.loadFile(iniFile, this.defaultEncode);
104 }
105
106 /**
107 * load the propeties file by specified file path and encodign
108 *
109 * @param instream input stream object
110 * @param encode specified encoding
111 * @return map of properteis content from the file
112 * @throws IOException IO about exception will throw out
113 */
114 public Map<String, String> loadFile(InputStream instream, String encode) throws IOException {
115
116 this.defaultEncode = encode;
117
118 BufferedReader in = new BufferedReader(new InputStreamReader(instream, encode));
119 String lineStr = null;
120 int commentPos = -1;
121 int valueBreakPos = -1;
122 String key = null;
123 String value = "";
124 int variabesNum = 0;
125 String variableKey = null;
126
127 while ((lineStr = in.readLine()) != null) {
128 lineStr = lineStr.trim();
129 if (lineStr.equals("")) {
130 continue;
131 }
132 if (lineStr.startsWith("#")) {
133 continue;
134 }
135
136 commentPos = lineStr.indexOf("#");
137 if (commentPos != -1) {
138 lineStr = lineStr.substring(0, commentPos);
139 }
140 valueBreakPos = lineStr.indexOf("=");
141 if (valueBreakPos == -1) {
142 setPropertiseValue(lineStr, "");
143 } else {
144 key = lineStr.substring(0, valueBreakPos).trim();
145 value = lineStr.substring(++valueBreakPos, lineStr.length()).trim();
146 if (value.indexOf("${") != -1) {
147
148 List<String> variables = parseVaraibles(value);
149 if (variables != null) {
150 variabesNum = variables.size();
151 for (int i = 0; i < variabesNum; i++) {
152 variableKey = variables.get(i);
153 if (variableKey != null && !variableKey.equals(key)) {
154 value = StringUtils.replace(value, "${" + variableKey + "}",
155 getPropertiesValue(variableKey, ""));
156 }
157 }
158 }
159 }
160 setPropertiseValue(key, value);
161 }
162 }
163 in.close();
164
165 return this.propContent;
166 }
167
168 /**
169 * load the propeties file by specified file path and encodign
170 * @param iniFile full file path
171 * @param encode specified encoding
172 * @return map of properteis content from the file
173 * @throws IOException IO about exception will throw out
174 */
175 public Map<String, String> loadFile(String iniFile, String encode) throws IOException {
176 if (iniFile == null) {
177 LOGGER.warn("null pointer of iniFile");
178 throw new NullPointerException("iniFile is set to be value of null");
179 }
180 if (iniFile.equals("")) {
181 throw new IOException("filename should not be null");
182 }
183 setIniFile(iniFile);
184
185 File file = new File(iniFile);
186 if (!file.exists()) {
187 file.createNewFile();
188 }
189 fileTime = file.lastModified();
190 InputStream inFile = new FileInputStream(file);
191 return loadFile(inFile, encode);
192 }
193
194 /**
195 * parse the format as ${..} variables
196 * @param field string to be parsed
197 * @return list object contains parsed variables
198 * if field is null or blank null value will be return
199 */
200 private List<String> parseVaraibles(String field) {
201 List<String> variables = new ArrayList<String>();
202
203 if (StringUtils.isBlank(field)) {
204 return null;
205 }
206
207 int len = field.length();
208 char keyChar;
209 boolean iskey = false;
210 StringBuffer tempStr = new StringBuffer();
211 for (int i = 0; i < len; i++) {
212 keyChar = field.charAt(i);
213
214 if (keyChar == '$') {
215 if ((++i < len) && (field.charAt(i) == '{')) {
216 iskey = true;
217 tempStr.setLength(0);
218 }
219 } else if (keyChar == '}') {
220 if (tempStr.length() > 0) {
221 variables.add(tempStr.toString());
222 }
223 iskey = false;
224 } else {
225 if (iskey) {
226 tempStr.append(keyChar);
227 }
228 }
229 }
230
231 return variables;
232 }
233
234 /**
235 * store the properties content to the opened file
236 * @throws IOException IO about exception will throw out
237 */
238 public void store() throws IOException {
239 this.store(this.iniFile);
240 }
241
242 /**
243 * store the properties content to the specified file
244 * @param iniFile full file path
245 * @throws IOException IO about exception will throw out
246 */
247 public void store(String iniFile) throws IOException {
248 this.store(iniFile, null);
249 }
250
251 /**
252 * store the properties content to the specified file
253 * and support to add comment
254 * if call this method as follow:
255 * store("c:\\test.ini", "Matthew update it");
256 * the comment will out like this:
257 * #Matthew update it
258 * #update time:2006-01-08 10:18:26
259 *
260 * @param iniFile full file path
261 * @param comment comment for this updating
262 * @throws IOException IOException IO about exception will throw out
263 */
264 public void store(String iniFile, String comment) throws IOException {
265 if (iniFile == null) {
266 LOGGER.warn("null pointer of iniFile");
267 throw new NullPointerException("iniFile is set to be value of null");
268 }
269 if (iniFile.equals("")) {
270 throw new IOException("filename should not be null");
271 }
272
273 if (this.propContent == null) {
274 return;
275 }
276
277 StringBuffer sbuff = new StringBuffer();
278 if (comment != null && (!comment.equals(""))) {
279 sbuff.append("#");
280 sbuff.append(comment);
281 sbuff.append("\r\n");
282 DateFormat dformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
283 sbuff.append("#update time:").append(dformat.format(new Date()));
284 sbuff.append("\r\n");
285 }
286
287 Iterator iter = this.propContent.entrySet().iterator();
288 String key, value;
289 while (iter.hasNext()) {
290 Map.Entry entry = (Map.Entry) iter.next();
291 key = (String) entry.getKey();
292 value = (String) entry.getValue();
293
294 sbuff.append(key);
295 sbuff.append("=");
296 sbuff.append(value);
297 sbuff.append("\r\n");
298 }
299
300 BufferedWriter wrf = new BufferedWriter(new FileWriter(iniFile, false));
301 wrf.write(sbuff.toString());
302 wrf.close();
303
304 }
305
306 /**
307 * get string properties value if the properties name not found null will be return
308 * @param key properties key
309 * @return properties value
310 */
311 public String getPropertiesValue(String key) {
312
313 return getPropertiesValue(key, null);
314 }
315
316 /**
317 * get string properties value if the properties name not found
318 * default value will be return.
319 * @param key properties key
320 * @param defValue properties value
321 * @return properties value
322 */
323 public String getPropertiesValue(String key, String defValue) {
324
325 if (isReloadOnchange) {
326 try {
327 reloadOnChange();
328 } catch (IOException e) {
329 LOGGER.warn("reload propeties file failed: reason:" + e.getMessage());
330 }
331 }
332
333 String strRet = defValue;
334 if (key != null && (!key.equals(""))) {
335 strRet = this.propContent.get(key);
336 if (strRet == null) {
337 return defValue;
338 }
339 }
340 return strRet;
341 }
342
343 /**
344 * reload the properties file.
345 *
346 * @throws IOException
347 */
348 private void reloadOnChange() throws IOException {
349 if (StringUtils.isBlank(iniFile)) {
350 return;
351 }
352
353 File file = new File(iniFile);
354 if (!file.exists()) {
355 propContent.clear();
356 return;
357 }
358
359 long fileLastModifytime = file.lastModified();
360 if (fileLastModifytime != fileTime) {
361 if (propContent != null) {
362 propContent.clear();
363 }
364 if (LOGGER.isInfoEnabled()) {
365 LOGGER.info("reloadOnChange() - reload ini file:" + iniFile);
366 }
367 loadFile(iniFile, defaultEncode);
368 }
369
370 }
371
372 /**
373 * get Integer properties value if the properties name not found
374 * default value will be return.
375 * @param key properties key
376 * @param defValue properties value
377 * @return properties value
378 */
379 public Integer getPropertiesInteger(String key, Integer defValue) {
380 int intRet = defValue;
381 String strValue = getPropertiesValue(key);
382 if (strValue != null) {
383 try {
384 intRet = Integer.parseInt(strValue);
385 } catch (Exception e) {
386 LOGGER.warn("parse String to Integer failed.");
387 }
388 }
389 return intRet;
390 }
391
392 /**
393 * get Float properties value if the properties name not found
394 * default value will be return.
395 *
396 * @param key properties key
397 * @param defValue properties value
398 * @return properties value
399 */
400 public Float getPropertiesFloat(String key, Float defValue) {
401 float floatRet = defValue;
402 String strValue = getPropertiesValue(key);
403 if (strValue != null) {
404 try {
405 floatRet = Float.parseFloat(strValue);
406 } catch (Exception e) {
407 LOGGER.warn("parse String to Float failed.");
408 }
409 }
410 return floatRet;
411 }
412
413 /**
414 * <p>
415 * set properties value. <code>null</code> value and key is not permitted.</p>
416 * @param key properties key
417 * @param value properties value
418 * @return return the previous value of the specified key
419 * in this property list, or null if it did not have one.
420 */
421 public Object setPropertiseValue(String key, String value) {
422 return this.propContent.put(key, value);
423 }
424
425 /**
426 * set integer properties value
427 * @param key properties key
428 * @param value properties value
429 * @return return the previous value of the specified key
430 * in this property list, or null if it did not have one.
431 */
432 public Object setPropertiseValue(String key, Integer value) {
433 return this.propContent.put(key, value.toString());
434 }
435
436 /**
437 * set float properties value
438 * @param key properties key
439 * @param value properties value
440 * @return return the previous value of the specified key
441 * in this property list, or null if it did not have one.
442 */
443 public Object setPropertiseValue(String key, Float value) {
444 return this.propContent.put(key, value.toString());
445 }
446
447 /**
448 * <p>
449 * get all properties keys.<br>
450 * <code>null</code> will be return if the properties is <code>null</code>
451 * </p>
452 * @return list type properties keys
453 */
454 public List<String> getAllKeys() {
455 if (propContent == null) {
456 return null;
457 }
458
459 Set<String> keys = propContent.keySet();
460 List<String> list = new LinkedList<String>(keys);
461 return list;
462 }
463
464 /**
465 * <p>
466 * get all peroperties keys and values<br>
467 * <code>null</code> will be return if the properties is <code>null</code>
468 * </p>
469 * @return map type properties keys and values
470 */
471 public Map<String, String> getAllKeyValues() {
472 return propContent;
473 }
474
475 /**
476 * @return the isReloadOnchange
477 */
478 public boolean isReloadOnchange() {
479 return isReloadOnchange;
480 }
481
482 /**
483 * @param isReloadOnchange the isReloadOnchange to set
484 */
485 public void setReloadOnchange(boolean isReloadOnchange) {
486 this.isReloadOnchange = isReloadOnchange;
487 }
488
489 /**
490 * @return the propContent
491 */
492 public Map<String, String> getPropContent() {
493 return propContent;
494 }
495
496 /**
497 * @param propContent the propContent to set
498 */
499 public void setPropContent(Map<String, String> propContent) {
500 this.propContent = propContent;
501 }
502
503 /**
504 * get the properties keys and values
505 * @return override toString method.
506 */
507 @Override
508 public String toString() {
509 StringBuffer sbuff = new StringBuffer();
510 sbuff.append("Properties values{");
511 if (this.propContent != null) {
512 Iterator iter = this.propContent.entrySet().iterator();
513 String key, value;
514 while (iter.hasNext()) {
515 Map.Entry entry = (Map.Entry) iter.next();
516 key = (String) entry.getKey();
517 value = (String) entry.getValue();
518
519 sbuff.append(key);
520 sbuff.append("=");
521 sbuff.append(value);
522 sbuff.append("\r\n");
523 }
524 }
525 sbuff.append("}");
526 return sbuff.toString();
527 }
528
529 }