原文地址:http://blog.csdn.net/benbenxiongyuan/article/details/53006097

参考地址:http://www.iteye.com/topic/156474

Properties调用store方法保存时,会把文件中原来的注释给冲掉,而且顺序会发生错乱,网上查找解决方案时,有人遇到了相同的问题,并给出了解决方案。

如下:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;/*** Properties调用store方法保存时,会把文件中原来的注释给冲掉,而且顺序会发生错乱,* 网上查找解决方案时,有人遇到了相同的问题,并给出了解决方案* * 改进java.util.Properties文件读写类,在读取properties文件的时候把注释和顺序格式都记录下来,操作时候也把添加顺序记录了,* 同时提供addComment()方法,可以添加注释,这样,经过处理的properties的可读性就能继续保持下来了,实现了SafeProperties.java,代码如下:* @author Administrator**/@SuppressWarnings("all")
public class SafeProperties extends Properties {private static final long serialVersionUID = 5011694856722313621L;private static final String keyValueSeparators = "=: \t\r\n\f";private static final String strictKeyValueSeparators = "=:";private static final String specialSaveChars = "=: \t\r\n\f#!";private static final String whiteSpaceChars = " \t\r\n\f";private PropertiesContext context = new PropertiesContext();public PropertiesContext getContext() {return context;}public synchronized void load(InputStream inStream) throws IOException {BufferedReader in;in = new BufferedReader(new InputStreamReader(inStream, "8859_1"));while (true) {// Get next lineString line = in.readLine();// intract property/comment stringString intactLine = line;if (line == null)return;if (line.length() > 0) {// Find start of keyint len = line.length();int keyStart;for (keyStart = 0; keyStart < len; keyStart++)if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1)break;// Blank lines are ignoredif (keyStart == len)continue;// Continue lines that end in slashes if they are not commentschar firstChar = line.charAt(keyStart);if ((firstChar != '#') && (firstChar != '!')) {while (continueLine(line)) {String nextLine = in.readLine();intactLine = intactLine + "\n" + nextLine;if (nextLine == null)nextLine = "";String loppedLine = line.substring(0, len - 1);// Advance beyond whitespace on new lineint startIndex;for (startIndex = 0; startIndex < nextLine.length(); startIndex++)if (whiteSpaceChars.indexOf(nextLine.charAt(startIndex)) == -1)break;nextLine = nextLine.substring(startIndex, nextLine.length());line = new String(loppedLine + nextLine);len = line.length();}// Find separation between key and valueint separatorIndex;for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++) {char currentChar = line.charAt(separatorIndex);if (currentChar == '\\')separatorIndex++;else if (keyValueSeparators.indexOf(currentChar) != -1)break;}// Skip over whitespace after key if anyint valueIndex;for (valueIndex = separatorIndex; valueIndex < len; valueIndex++)if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)break;// Skip over one non whitespace key value separators if anyif (valueIndex < len)if (strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1)valueIndex++;// Skip over white space after other separators if anywhile (valueIndex < len) {if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1)break;valueIndex++;}String key = line.substring(keyStart, separatorIndex);String value = (separatorIndex < len) ? line.substring(valueIndex, len) : "";// Convert then store key and valuekey = loadConvert(key);value = loadConvert(value);// memorize the property also with the whold string
                    put(key, value, intactLine);} else {// memorize the comment string
                    context.addCommentLine(intactLine);}} else {// memorize the string even the string is empty
                context.addCommentLine(intactLine);}}}/** Converts encoded \uxxxx to unicode chars and changes special saved* chars to their original forms*/private String loadConvert(String theString) {char aChar;int len = theString.length();StringBuffer outBuffer = new StringBuffer(len);for (int x = 0; x < len;) {aChar = theString.charAt(x++);if (aChar == '\\') {aChar = theString.charAt(x++);if (aChar == 'u') {// Read the xxxxint value = 0;for (int i = 0; i < 4; i++) {aChar = theString.charAt(x++);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.");}}outBuffer.append((char) value);} else {if (aChar == 't')outBuffer.append('\t'); /* ibm@7211 */else if (aChar == 'r')outBuffer.append('\r'); /* ibm@7211 */else if (aChar == 'n') {/** ibm@8897 do not convert a \n to a line.separator* because on some platforms line.separator is a String* of "\r\n". When a Properties class is saved as a file* (store()) and then restored (load()) the restored* input MUST be the same as the output (so that* Properties.equals() works).* */outBuffer.append('\n'); /* ibm@8897 ibm@7211 */} else if (aChar == 'f')outBuffer.append('\f'); /* ibm@7211 */else/* ibm@7211 */outBuffer.append(aChar); /* ibm@7211 */}} elseoutBuffer.append(aChar);}return outBuffer.toString();}public synchronized void store(OutputStream out, String header) throws IOException {BufferedWriter awriter;awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));if (header != null)writeln(awriter, "#" + header);List entrys = context.getCommentOrEntrys();for (Iterator iter = entrys.iterator(); iter.hasNext();) {Object obj = iter.next();if (obj.toString() != null) {writeln(awriter, obj.toString());}}awriter.flush();}private static void writeln(BufferedWriter bw, String s) throws IOException {bw.write(s);bw.newLine();}private boolean continueLine(String line) {int slashCount = 0;int index = line.length() - 1;while ((index >= 0) && (line.charAt(index--) == '\\'))slashCount++;return (slashCount % 2 == 1);}/** Converts unicodes to encoded \uxxxx and writes out any of the* characters in specialSaveChars with a preceding slash*/private String saveConvert(String theString, boolean escapeSpace) {int len = theString.length();StringBuffer outBuffer = new StringBuffer(len * 2);for (int x = 0; x < len; x++) {char aChar = theString.charAt(x);switch (aChar) {case ' ':if (x == 0 || escapeSpace)outBuffer.append('\\');outBuffer.append(' ');break;case '\\':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;default:if ((aChar < 0x0020) || (aChar > 0x007e)) {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 {if (specialSaveChars.indexOf(aChar) != -1)outBuffer.append('\\');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' };public synchronized Object put(Object key, Object value) {context.putOrUpdate(key.toString(), value.toString());return super.put(key, value);}public synchronized Object put(Object key, Object value, String line) {context.putOrUpdate(key.toString(), value.toString(), line);return super.put(key, value);}public synchronized Object remove(Object key) {context.remove(key.toString());return super.remove(key);}class PropertiesContext {private List commentOrEntrys = new ArrayList();public List getCommentOrEntrys() {return commentOrEntrys;}public void addCommentLine(String line) {commentOrEntrys.add(line);}public void putOrUpdate(PropertyEntry pe) {remove(pe.getKey());commentOrEntrys.add(pe);}public void putOrUpdate(String key, String value, String line) {PropertyEntry pe = new PropertyEntry(key, value, line);remove(key);commentOrEntrys.add(pe);}public void putOrUpdate(String key, String value) {PropertyEntry pe = new PropertyEntry(key, value);int index = remove(key);commentOrEntrys.add(index, pe);}public int remove(String key) {for (int index = 0; index < commentOrEntrys.size(); index++) {Object obj = commentOrEntrys.get(index);if (obj instanceof PropertyEntry) {if (obj != null) {if (key.equals(((PropertyEntry) obj).getKey())) {commentOrEntrys.remove(obj);return index;}}}}return commentOrEntrys.size();}class PropertyEntry {private String key;private String value;private String line;public String getLine() {return line;}public void setLine(String line) {this.line = line;}public PropertyEntry(String key, String value) {this.key = key;this.value = value;}/*** @param key* @param value* @param line*/public PropertyEntry(String key, String value, String line) {this(key, value);this.line = line;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String toString() {if (line != null) {return line;}if (key != null && value != null) {String k = saveConvert(key, true);String v = saveConvert(value, false);return k + "=" + v;}return null;}}}/*** @param comment*/public void addComment(String comment) {if (comment != null) {context.addCommentLine("#" + comment);}}}

View Code

转载于:https://www.cnblogs.com/xiehongwei/p/8033446.html

java.util.Properties类,保存时保留注释及格式不变相关推荐

  1. java集合——java.util.Properties类

    [0]README 0.1)以下全文转自 : http://trans.blog.51cto.com/503170/110227/ [1]认识properties文件 1. properties文件是 ...

  2. java.util.Properties类的介绍-配置文件的读写【-Z-】

    简介:java.util.Properties是对properties这类配置文件的映射.支持key-value类型和xml类型两种. #打头的是注释行,Properties会忽略注释.允许只有key ...

  3. Java中Properties类的学习总结

    学习目标: 1.认识properties文件,理解其含义,会正确创建properties文件. 2.会使用java.util.Properties类来操作properties文件. 一.认识prope ...

  4. Java属性文件– java.util.Properties

    Java properties file are used to store key-value pair configuration. java.util.Properties class is u ...

  5. java properties map_为什么java.util.Properties实现Map而不是Map

    java.util.Properties类用于表示键和值都是字符串的映射.这是因为Properties对象用于读取.properties文件,这些文件是文本文件. 那么,为什么在Java 5中他们改进 ...

  6. [Java基础] Properties类的基本操作和介绍

    引言 Java中的.properties文件是一种配置文件,主要用于表达配置信息:通俗来说,存放的数据就像是Map中的key和value的对应关系一样:这样就可以通过键值对来对属性进行匹配,并且属性列 ...

  7. java.util.Properties

    ava.util.Properties是对properties这类配置文件的映射.支持key-value类型和xml类型两种 首先,新建一个文件,如图: 然后再Java代码段输入如下代码: impor ...

  8. java.util.Stack类简介

    转载自  java.util.Stack类简介 Stack是一个后进先出(last in first out,LIFO)的堆栈,在Vector类的基础上扩展5个方法而来 Deque(双端队列)比起St ...

  9. JDK中提供的实现——通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例

    JDK中提供的实现 在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例. 1 ...

最新文章

  1. 打开快手,体验流畅的单目三维手势技术
  2. java.lang.OutOfMemoryError: Java heap space的解决办法
  3. No-PDO-Models-MySQL数据库层抽象类
  4. python爬虫实战-python爬虫实战一:分析豆瓣中最新电影的影评
  5. PHP 安全问题入门:10 个常见安全问题 + 实例讲解
  6. CentOS 7 安装nexus
  7. LiveVideoStack线上分享第三季(九):《街舞》《长安十二时辰》背后的文娱大脑...
  8. python中history()_keras中的History对象用法
  9. Python四大金刚
  10. 我的编程之路(二十五) 上海的老同学
  11. 依存可视化︱Dependency Viewer——南京大学自然语言处理研究组
  12. 程序不能使用中文名_理线好帮手 骨伽 Bunker RGB 鼠标线夹使用心得
  13. CAPL可以读写的几种文件
  14. matlab 安装 cvx 和 mosek 以及 gurobi
  15. tidb分布式数据库_TiDB如何在分布式数据库中结合OLTP和OLAP
  16. TMS570-4-RTI_DWD看门狗
  17. 最难学的10大编程语言排行榜,Java只排第三,第一名出乎意料
  18. Axure实战案例——页面设计
  19. HTML表格和样式及选择器
  20. python pdfminer的功能_python:pdfminer接口测试

热门文章

  1. 让FX1.1的NotifyIcon支持BalloonTip(2)
  2. java创建datetime_Java OffsetDateTime ofInstant()用法及代码示例
  3. 浏览器对象模型BOM
  4. Python单引号、双引号和三双引号的区别
  5. 七牛云:调用七牛OCR接口,几行代码识别身份证信息
  6. 拒绝“割韭菜”— 谈谈区块链正经的商用场景!
  7. 二十年后的回眸(5)——一部单车闯天下
  8. Codeforces 861 B Which floor? 思维
  9. Spring Data JPA单元测试 Not a managed type
  10. MariaDB Galera Cluster环境搭建及高可用测试