我在工作中接到一项任务,需要保留客户端设置。这些设置由我正在实现的框架的 C# 版本中的 XML 文件表示,它表示具有最多六级层次结构的对象。此外,不同级别中的对象数量有时是任意的,例如 ArrayList。遗憾的是,由于需要能够直接编辑文件,因此不能选择对象序列化。这不仅仅是暗示我必须将这些设置的持久性实现为 .properties 文件,但我担心这是否是一个好主意。
据我所知,.properties 文件只能以与 HashMap 相同的方式使用,并且键值对仅包含字符串。复杂对象的表示似乎只能使用长而复杂的键字符串,表示每个元素的整个“路径”,包括它在可能的几个列表中的单独索引。
filters.filter3.traces.rule4.add1.value="8"
我还没有找到任何合适的方法来在 .properties 文件中保存分层对象,但我也没有找到任何明确的证据来证明这是不可能的。
那么,.properties 文件适合存储分层设置对象吗?或者我应该将我的属性实现为 XML 文件或 JSON?
最佳答案
您有一个 log4j
形式的完美示例:这是来自 here 的属性示例.
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File = logs/bensApps.log
log4j.appender.R.Append = true
log4j.appender.R.DatePattern = '.'yyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n
如果这些键中有层次结构,例如:
Map<String,Object> root = new HashMap<>();
root.put("level1", "foobar");
root.put("level2", Collections.singletonMap("p", "foobar");
您可以将其翻译为:
level1=foobar
level2.p=foobar
并且在读取文件时,将.
拆分为子图:
Map<String, Object> root = new HashMap<>();
Properties propz = new Properties();
// load from your file
for (Map.Entry<String,Object> entry : propz.entrySet()) {
String[] path = entry.getKey().split('\\.');
Map<String,Object> parent = root;
int n = path.length - 1;
for (int i = 0; i < n; ++i) {
String p = path[i];
Object child = parent.get(p);
if (null == child) {
Map<String,Object> _p = new HashMap<>();
parent.put(p, _p);
parent = _p;
} else if (child instanceof Map) {
parent = (Map<String,Objext>) child;
} else {
// it is up to you to do something when the path extends beyond a "final" key
}
}
parent.put(path[n], entry.getValue());
}
但是,这是一种“重新发明轮子”模式,其他答案指出您可能比自己做更好的解决方案。这个例子还向您展示了一种问题:
p1=foobar
p1.p2=foobar
对于机器生成的属性,这种情况不会发生,异常(exception)可能是最好的答案。但在人类操纵属性的情况下,这可能具有一定的意义。
顺便说一句,由于 Java 7 附带了 JAXB,因此您也可以使用完整的 XML 来完成此操作,而不需要额外的库。并使用某种层次结构。
关于java - .properties 文件是否适合存储分层设置对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25970045/