今天遇到一个小需求:由于java.util.Properties读取属性文件时会忽略注释,当写回去的时候,注释都没了。恰好一个项目中的配置文件会在部署后被某个Java程序修改一下,但修改了之后注释全没了,可能会给以后的参数调整带来困难。所以要解决这个问题。
正好最近在看Java集合框架类库,干脆搞它一把。但是时间有限,也不能从头搞起,那就基于Properties搞搞看。
先确定要解决什么问题。首要问题是,读取一个属性文件,然后写回去,注释全没了。从Properties代码片段里找一下原因:
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
当Properties从一个字节流中加载属性时,会通过一个行读取器java.util.Properties.LineReader。
/* Read in a "logical line" from an InputStream/Reader, skip all comment
* and blank lines and filter out those leading whitespace characters
* (\u0020, \u0009 and \u000c) from the beginning of a "natural line".
* Method returns the char length of the "logical line" and stores
* the line in "lineBuf".
*/
class LineReader {
public LineReader(InputStream inStream) {
this.inStream = inStream;
inByteBuf = new byte[8192];
}
从行读取器的注释上看,是在读行的时候跳过了comment。
要解决这个问题好办,只要修改下这个行读取器,把comment放行就哦了。但是光把comment放开,那怎么保存呢?java.util.Properties扩展自java.util.Hashtable,键值对存在java.util.Hashtable.Entry里。这货也没法扩展,只能想办法在其他地方把comment存起来。首要问题有解决方案了。
还有一个小问题,由于java.util.Properties扩展自java.util.Hashtable,并不保证key的顺序。所以读取然后写回文件,里面属性的顺序都乱了。想个办法保证一下顺序,猛然想到了java.util.LinkedHashMap,有木有,这个太合适了。
最后赶紧写了一下,代码片段如下。
/**
* CommentedProperties
* 针对Properties进行扩展的工具类
*
* 扩展的两个主要功能:
* 1.对Properties文件中注释的保存。
* CommentedProperties在读取和保存Properties文件时,会将其注释
* 一起读取保存。CommentedProperties中会提供方法来根据key获取
* 相应注释。在CommentedProperties中添加一个K-V对时,也会提供
* 添加相应注释的方法。
*
* 2.对Properties文件中Key值顺序的保证。
* CommentedProperties会保证Key的顺序。从一个Properties文件中
* 读取所有K-V对,保存到另一个Properties文件时,Key的顺序不会
* 改变。
*
*
* @author BrokenDreams
*/
public class CommentedProperties{
/**
* 内部属性表
*/
private final Properties props;
/**
* 保存key与comment的映射,
* 同时利用这个映射来保证key的顺序。
*/
private final LinkedHashMap<String, String> keyCommentMap = new LinkedHashMap<String, String>();
private static final String BLANK = "";
public CommentedProperties() {
super();
props = new Properties();
}
public CommentedProperties(Properties defaults) {
super();
props = new Properties(defaults);
}
应该有更好的方式解决这个问题,但解决问题的同时顺序熟悉一下JDK相关类的代码页不是坏事,呵呵。这个类基本上能用了,可能还有很多可改进的地方。
代码见附件,有用得着的可以下载来看看,HOHO,回家!