【问题标题】:Properties.store() - suppress timestamp commentProperties.store() - 禁止时间戳注释
【发布时间】:2011-09-05 06:35:16
【问题描述】:

是否可以强制Properties不在前面添加日期注释?我的意思是这里的第一行:

#Thu May 26 09:43:52 CEST 2011
main=pkg.ClientMain
args=myargs

我想完全摆脱它。我需要我的配置文件是不同的,除非有一个有意义的改变。

【问题讨论】:

    标签: java properties


    【解决方案1】:

    猜不出来。此时间戳打印在 private method on Properties 中,并且没有属性可以控制该行为。

    我想到的唯一想法:子类Properties,覆盖store并复制/粘贴store0方法的内容,这样就不会打印日期注释。

    或者 - 提供一个自定义的BufferedWriter 打印所有的第一行(如果你添加真正的cmets将会失败,因为自定义的cmets在时间戳之前打印...)

    【讨论】:

    • 我必须按照你的建议去做。子类属性能够具有一致的排序并且没有时间戳。不是最好的做法,复制粘贴私有方法的源代码很讨厌。但这是我找到的唯一方法。
    • 工作,必须为它复制多个私有方法。希望他们有一天会添加一个标志或其他东西。
    • 而不是跳过第一行,通过使用正则表达式(匹配时间戳注释)在 cmets 的第一行中查找(并跳过)第一个匹配项,很容易保留真正的 cmets。跨度>
    【解决方案2】:

    鉴于源代码或属性,不,这是不可能的。顺便说一句,由于 Properties 实际上是一个哈希表,并且它的键因此没有排序,所以无论如何你不能依赖属性总是以相同的顺序。

    如果我有这个要求,我会使用自定义算法来存储属性。使用 Properties 的源代码作为入门。

    【讨论】:

    • String.hashCode() 定义明确且稳定,这不就意味着哈希表中的条目顺序是一致的吗?
    • +1 - 未排序:很好。之前遇到过这个问题,并且确实将属性转储到“行集合”(列表),按字母顺序对它们进行排序并将集合转储到文件中。
    • @Konrad - 相同的一组属性(键)将始终以相同的顺序打印,但如果您添加一个键,则属性文件可能会被打乱......至少不能保证其他键保持顺序
    【解决方案3】:

    基于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, "");
        }
    

    【讨论】:

      【解决方案4】:

      如果您尝试在给 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);
          }
      }
      

      【讨论】:

        【解决方案5】:

        当有意义的配置更改发生时,您能否不只是在应用程序的某个地方进行标记,并且仅在已设置的情况下写入文件?

        您可能想查看Commons Configuration,它在写入和读取属性文件等内容时具有更大的灵活性。特别是,它具有尝试编写与现有属性文件完全相同的属性文件(包括间距、cmets 等)的方法。

        【讨论】:

          【解决方案6】:

          您可以按照这个 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);
          

          【讨论】:

            猜你喜欢
            • 2022-11-02
            • 2021-06-02
            • 2015-05-23
            • 1970-01-01
            • 2013-02-08
            • 2019-09-19
            • 1970-01-01
            • 1970-01-01
            • 2011-09-01
            相关资源
            最近更新 更多