【发布时间】:2011-09-05 06:35:16
【问题描述】:
是否可以强制Properties不在前面添加日期注释?我的意思是这里的第一行:
#Thu May 26 09:43:52 CEST 2011
main=pkg.ClientMain
args=myargs
我想完全摆脱它。我需要我的配置文件是不同的,除非有一个有意义的改变。
【问题讨论】:
标签: java properties
是否可以强制Properties不在前面添加日期注释?我的意思是这里的第一行:
#Thu May 26 09:43:52 CEST 2011
main=pkg.ClientMain
args=myargs
我想完全摆脱它。我需要我的配置文件是不同的,除非有一个有意义的改变。
【问题讨论】:
标签: java properties
猜不出来。此时间戳打印在 private method on Properties 中,并且没有属性可以控制该行为。
我想到的唯一想法:子类Properties,覆盖store并复制/粘贴store0方法的内容,这样就不会打印日期注释。
或者 - 提供一个自定义的BufferedWriter 打印所有但的第一行(如果你添加真正的cmets将会失败,因为自定义的cmets在时间戳之前打印...)
【讨论】:
鉴于源代码或属性,不,这是不可能的。顺便说一句,由于 Properties 实际上是一个哈希表,并且它的键因此没有排序,所以无论如何你不能依赖属性总是以相同的顺序。
如果我有这个要求,我会使用自定义算法来存储属性。使用 Properties 的源代码作为入门。
【讨论】:
String.hashCode() 定义明确且稳定,这不就意味着哈希表中的条目顺序是一致的吗?
基于https://stackoverflow.com/a/6184414/242042,这是我编写的实现,它去掉了第一行并对键进行排序。
public class CleanProperties extends Properties {
private static class StripFirstLineStream extends FilterOutputStream {
private boolean firstlineseen = false;
public StripFirstLineStream(final OutputStream out) {
super(out);
}
@Override
public void write(final int b) throws IOException {
if (firstlineseen) {
super.write(b);
} else if (b == '\n') {
firstlineseen = true;
}
}
}
private static final long serialVersionUID = 7567765340218227372L;
@Override
public synchronized Enumeration<Object> keys() {
return Collections.enumeration(new TreeSet<>(super.keySet()));
}
@Override
public void store(final OutputStream out, final String comments) throws IOException {
super.store(new StripFirstLineStream(out), null);
}
}
打扫是这样的
final Properties props = new CleanProperties();
try (final Reader inStream = Files.newBufferedReader(file, Charset.forName("ISO-8859-1"))) {
props.load(inStream);
} catch (final MalformedInputException mie) {
throw new IOException("Malformed on " + file, mie);
}
if (props.isEmpty()) {
Files.delete(file);
return;
}
try (final OutputStream os = Files.newOutputStream(file)) {
props.store(os, "");
}
【讨论】:
如果您尝试在给 xxx.conf 文件中进行修改,它将很有用。
在 store 方法中用于跳过第一行 (#Thu May 26 09:43:52 CEST 2011) 的 write 方法。 write 方法一直运行到第一行的末尾。之后就可以正常运行了。
public class CleanProperties extends Properties {
private static class StripFirstLineStream extends FilterOutputStream {
private boolean firstlineseen = false;
public StripFirstLineStream(final OutputStream out) {
super(out);
}
@Override
public void write(final int b) throws IOException {
if (firstlineseen) {
super.write(b);
} else if (b == '\n') {
// Used to go to next line if did use this line
// you will get the continues output from the give file
super.write('\n');
firstlineseen = true;
}
}
}
private static final long serialVersionUID = 7567765340218227372L;
@Override
public synchronized Enumeration<java.lang.Object> keys() {
return Collections.enumeration(new TreeSet<>(super.keySet()));
}
@Override
public void store(final OutputStream out, final String comments)
throws IOException {
super.store(new StripFirstLineStream(out), null);
}
}
【讨论】:
当有意义的配置更改发生时,您能否不只是在应用程序的某个地方进行标记,并且仅在已设置的情况下写入文件?
您可能想查看Commons Configuration,它在写入和读取属性文件等内容时具有更大的灵活性。特别是,它具有尝试编写与现有属性文件完全相同的属性文件(包括间距、cmets 等)的方法。
【讨论】:
您可以按照这个 Stack Overflow 帖子来处理这个问题以保持顺序:
按标准顺序编写: How can I write Java properties in a defined order?
然后将属性写入字符串并根据需要删除 cmets。最后写入文件。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
properties.store(baos,null);
String propertiesData = baos.toString(StandardCharsets.UTF_8.name());
propertiesData = propertiesData.replaceAll("^#.*(\r|\n)+",""); // remove all comments
FileUtils.writeStringToFile(fileTarget,propertiesData,StandardCharsets.UTF_8);
// you may want to validate the file is readable by reloading and doing tests to validate the expected number of keys matches
InputStream is = new FileInputStream(fileTarget);
Properties testResult = new Properties();
testResult.load(is);
【讨论】: