读书人

java操作properties资料持久键值对和注

发布时间: 2012-11-21 08:23:26 作者: rapoo

java操作properties文件持久键值对和注解到文件

properties文件在应用系统很长用,写properties文件和加载properties文件都很简单也是很常用的方法。

持久化键值对Properties类提供了store几个方法,其中只能在第一行加入注释,之前写的注释也会丢失并且不支持中文。

因此改进写一下代码,对注解中文的支持以及持久化过程中不丢失注解,不多说,上代码。

package com.zohan.www.util;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.OutputStreamWriter;import java.util.Date;import java.util.Enumeration;import java.util.HashMap;import java.util.Map;import java.util.Set;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.apache.commons.io.FileUtils;import org.apache.commons.lang3.StringUtils;/** * @ClassName: Properties * @Description: 重写Properties类中的部分方法 在保存过程中不丢失注释 * @author zohan inlw@sina.com * @date 2012-10-24 下午10:31:54 * @version 0.1.1 修改对 键值对中存在等号的 *  */public class Properties extends java.util.Properties {/** 源文件地址 */private String filePath = null;/** 参考文件地址 */private String referFile = null;/** * 存放用户放置的 key\value */private Map<String, String> map = new HashMap<String, String>();/** * @Fields serialVersionUID :(用一句话描述这个变量表示什么) */private static final long serialVersionUID = 1L;/** * @throws IOException * @Title: load * @Description: 增加load方法, * @param file *            设定文件 * @return void 返回类型 * @throws */public void load(File file) throws IOException {if (null != file)this.filePath = file.getPath();FileInputStream fis = new FileInputStream(file);super.load(fis);fis.close();}/* * (non-Javadoc) *  * @see java.util.Properties#getProperty(java.lang.String) */@Overridepublic String getProperty(String key) {String value = map.get(key);return null == value ? super.getProperty(key) : value;}/* * (non-Javadoc) *  * @see java.util.Properties#setProperty(java.lang.String, java.lang.String) */@Overridepublic synchronized Object setProperty(String key, String value) {return map.put(key, value);}/* * (non-Javadoc) *  * @see java.util.Properties#stringPropertyNames() */@Overridepublic Set<String> stringPropertyNames() {return super.stringPropertyNames();}/** *  * @Title: store * @Description:把键值对持久化,包括注释 加载的时候请使用public void load(File file) 方法 * @param target * @param comments * @throws Exception *             设定文件 * @return void 返回类型 * @throws */public void store(String target, String comments) throws Exception {// filePath 不为空且存在File inFile = null;String temp = System.getProperty("java.io.tmpdir");temp = temp.endsWith(File.separator) ? temp : temp.concat(File.separator);if (!StringUtils.isEmpty(filePath)) {inFile = new File(filePath);if (inFile.exists()) {referFile = temp.concat(inFile.getName());}}inFile = new File(filePath);// filePath 为null targetFile作为 参考文件读取if (StringUtils.isEmpty(filePath) && !inFile.exists()) {throw new Exception("参考文件不能为空");}// referFile 为空选择target 为参照文件if (StringUtils.isEmpty(referFile)) {referFile = temp.concat(inFile.getName());}FileUtils.copyFile(inFile, new File(referFile));store0(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(target), "utf-8")), comments, true);new File(referFile).delete();}/** *  * @Title: store0 * @Description: 重写父类的写入文件方法,将注释也写入文件 * @param @param bw * @param @param comments * @param @param escUnicode * @param @throws IOException 设定文件 * @return void 返回类型 * @throws */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) {Map<String, String> temp = new HashMap<String, String>();for (Enumeration e = keys(); e.hasMoreElements();) {String key = (String) e.nextElement();String val = (String) get(key);temp.put(key, val);}for (String key : map.keySet()) {temp.put(key, map.get(key));}BufferedReader br = new BufferedReader(new FileReader(referFile));String line = "";while ((line = br.readLine()) != null) {if (line.length() == 0) {bw.newLine();} else if (line.trim().startsWith("#")) {writeCommentsLine(bw, line);} else {// 获取key(^[^=]*(\\=)?[^=]*)=Pattern p = Pattern.compile("(^[^=]*)=");Matcher m = p.matcher(line.replaceAll("\\\\=", "ab"));String key = "";if (m.find()) {key = m.group(1);key = line.substring(0, key.length());}key = key.replaceAll("\\\\=", "=");String value = temp.remove(key.trim());if (StringUtils.isEmpty(value)) {String v = line.replace(key, "");if (StringUtils.isEmpty(v)) {value = "";} else {if (v.trim().startsWith("=")) {value = v.substring(1);} else {value = temp.get(key);}}}key = saveConvert(key.trim(), true, escUnicode);/* * No need to escape embedded and trailing spaces for value, * hence pass false to flag. */value = saveConvert(value.trim(), false, escUnicode);bw.write(key + "=" + value);bw.newLine();}}br.close();for (String key : temp.keySet()) {String value = map.get(key);key = saveConvert(key.trim(), true, escUnicode);if (!StringUtils.isEmpty(value)) {value = saveConvert(value.trim(), false, escUnicode);} else {value = "";}bw.write(key + "=" + value);bw.newLine();}}bw.flush();}/* * Converts unicodes to encoded \uxxxx and escapes special characters * with a preceding slash */private String saveConvert(String theString, boolean escapeSpace,boolean escapeUnicode) {int len = theString.length();int bufLen = len * 2;if (bufLen < 0) {bufLen = Integer.MAX_VALUE;}StringBuffer outBuffer = new StringBuffer(bufLen);for (int x = 0; x < len; x++) {char aChar = theString.charAt(x);// Handle common case first, selecting largest block that// avoids the specials belowif ((aChar > 61) && (aChar < 127)) {if (aChar == '\\') {outBuffer.append('\\');outBuffer.append('\\');continue;}outBuffer.append(aChar);continue;}switch (aChar) {case ' ':if (x == 0 || escapeSpace)outBuffer.append('\\');outBuffer.append(' ');break;case '\t':outBuffer.append('\\');outBuffer.append('t');break;case '\n':outBuffer.append('\\');outBuffer.append('n');break;case '\r':outBuffer.append('\\');outBuffer.append('r');break;case '\f':outBuffer.append('\\');outBuffer.append('f');break;case '=': // Fall throughcase ':': // Fall throughcase '#': // Fall throughcase '!':outBuffer.append('\\');outBuffer.append(aChar);break;default:if (((aChar < 0x0020) || (aChar > 0x007e)) & escapeUnicode) {outBuffer.append('\\');outBuffer.append('u');outBuffer.append(toHex((aChar >> 12) & 0xF));outBuffer.append(toHex((aChar >> 8) & 0xF));outBuffer.append(toHex((aChar >> 4) & 0xF));outBuffer.append(toHex(aChar & 0xF));} else {outBuffer.append(aChar);}}}return outBuffer.toString();}/** * Convert a nibble to a hex character *  * @param nibble *            the nibble to convert. */private static char toHex(int nibble) {return hexDigit[(nibble & 0xF)];}/** A table of hex digits */private static final char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6','7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };/** *  * @Title: writeCommentsLine * @Description: 无特殊写法 * @param @param bw * @param @param comments * @param @throws IOException 设定文件 * @return void 返回类型 * @throws */private static void writeCommentsLine(BufferedWriter bw, String comments)throws IOException {bw.write(comments);bw.newLine();}/** *  * @Title: writeComments * @Description:拷贝类的写注解方式 * @param @param bw * @param @param comments * @param @throws IOException 设定文件 * @return void 返回类型 * @throws */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();}/** * @throws Exception * @Title: main * @Description: 测试文件 * @param @param args 设定文件 * @return void 返回类型 * @throws */public static void main(String[] args) throws Exception {Properties pro = new Properties();File file = new File("e:\\ss.properties");try {// 采用File参数pro.load(file);pro.setProperty("zohan", "zohan");System.out.println(pro.get("zohan"));// 持久化键值对pro.store("e:\\ss.properties", null);} catch (IOException e) {e.printStackTrace();}}}

? ? 前两天的代码里,有bug,不支持键值对中有等号,今天修复了bug重新发一次

读书人网 >软件架构设计

热点推荐