28

基本上,我必须通过 Java 应用程序覆盖 .properties 文件中的某个属性,但是当我使用 Properties.setProperty() 和 Properties.Store() 时,它会覆盖整个文件,而不仅仅是那个属性。

我尝试使用 append = true 构建 FileOutputStream,但它添加了另一个属性并且不会删除/覆盖现有属性。

如何对其进行编码,以便设置一个属性覆盖该特定属性,而不覆盖整个文件?

编辑:我尝试读取文件并添加到它。这是我更新的代码:

FileOutputStream out = new FileOutputStream("file.properties");
FileInputStream in = new FileInputStream("file.properties");
Properties props = new Properties();

props.load(in);
in.close();

props.setProperty("somekey", "somevalue");
props.store(out, null);
out.close();
4

8 回答 8

21

PropertiesAPI 不提供在属性文件中添加/替换/删除属性的任何方法。API 支持的模型是从文件加载所有属性,对内存中的Properties对象进行更改,然后将所有属性存储到文件(相同或不同)。

PropertiesAPI 在这方面并不罕见。实际上,如果不重写整个文件,就很难实现文本文件的就地更新。这种困难是现代操作系统实现文件/文件系统的方式的直接后果。

如果您真的需要进行增量更新,那么您需要使用某种数据库来保存属性,而不是“.properties”文件。


其他答案以各种形式提出了以下方法:

  1. 将文件中的属性加载到Properties对象中。
  2. 更新Properties对象。
  3. 将对象保存Properties在现有文件的顶部。

这适用于某些用例。但是加载/保存可能会重新排序属性,删除嵌入的注释和空白。这些事情可能很重要1

另一点是这涉及重写整个属性文件,OP 明确尝试2来避免。


1 - 如果 API 按设计者的意图使用,则属性顺序、嵌入的注释等都无关紧要。但是让我们假设 OP 这样做是出于“务实的原因”。2 -避免这种
情况并不实际;见较早。

于 2011-09-18T14:36:54.813 回答
17

您可以使用Apache Commons Configuration中的 PropertiesConfiguration 。

在版本 1.X 中:

PropertiesConfiguration config = new PropertiesConfiguration("file.properties");
config.setProperty("somekey", "somevalue");
config.save();

从 2.0 版开始:

Parameters params = new Parameters();
FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
    new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
    .configure(params.properties()
        .setFileName("file.properties"));
Configuration config = builder.getConfiguration();
config.setProperty("somekey", "somevalue");
builder.save();
于 2013-03-20T11:27:12.413 回答
1

属性文件是为应用程序提供配置的一种简单方法,但不一定是进行编程的、用户特定的定制的好方法,这正是您发现的原因。

为此,我会使用Preferences API。

于 2011-09-18T14:43:45.420 回答
1

我执行以下方法:-

  1. 读取文件并加载属性对象
  2. 使用“.setProperty”方法更新或添加新属性。(setProperty 方法优于 .put 方法,因为它可以用于插入和更新属性对象)
  3. 将属性对象写回文件以使文件与更改保持同步。
于 2016-10-04T06:33:43.190 回答
0
public class PropertiesXMLExample {
    public static void main(String[] args) throws IOException {

    // get properties object
    Properties props = new Properties();

    // get path of the file that you want
    String filepath = System.getProperty("user.home")
            + System.getProperty("file.separator") +"email-configuration.xml";

    // get file object
    File file = new File(filepath);

    // check whether the file exists
    if (file.exists()) {
        // get inpustream of the file
        InputStream is = new FileInputStream(filepath);

        // load the xml file into properties format
        props.loadFromXML(is);

        // store all the property keys in a set 
        Set<String> names = props.stringPropertyNames();

        // iterate over all the property names
        for (Iterator<String> i = names.iterator(); i.hasNext();) {
            // store each propertyname that you get
            String propname = i.next();

            // set all the properties (since these properties are not automatically stored when you update the file). All these properties will be rewritten. You also set some new value for the property names that you read
            props.setProperty(propname, props.getProperty(propname));
        }

        // add some new properties to the props object
        props.setProperty("email.support", "donot-spam-me@nospam.com");
        props.setProperty("email.support_2", "donot-spam-me@nospam.com");

       // get outputstream object to for storing the properties into the same xml file that you read
        OutputStream os = new FileOutputStream(
                System.getProperty("user.home")
                        + "/email-configuration.xml");

        // store the properties detail into a pre-defined XML file
        props.storeToXML(os, "Support Email", "UTF-8");

        // an earlier stored property
        String email = props.getProperty("email.support_1");

        System.out.println(email);
      }
   }
}

该程序的输出将是:

support@stackoverflow.com
于 2013-06-25T02:49:57.223 回答
0

请使用仅更新文件行而不是使用属性,例如

public static void updateProperty(String key, String oldValue, String newValue)
{
    File f = new File(CONFIG_FILE);
    try {
        List<String> fileContent = new ArrayList<>(Files.readAllLines(f.toPath(), StandardCharsets.UTF_8));

        for (int i = 0; i < fileContent.size(); i++) {
            if (fileContent.get(i).replaceAll("\\s+","").equals(key + "=" + oldValue)) {
                fileContent.set(i, key + " = " + newValue);
                break;
            }
        }
        Files.write(f.toPath(), fileContent, StandardCharsets.UTF_8);
    } catch (Exception e) {
        
    }
}
于 2022-02-08T16:34:00.743 回答
-1

导入java.io.*;

导入 java.util.*;

类 WritePropertiesFile

{

         public static void main(String[] args) {
    try {
        Properties p = new Properties();
        p.setProperty("1", "one");
        p.setProperty("2", "two");
        p.setProperty("3", "three");

        File file = new File("task.properties");
        FileOutputStream fOut = new FileOutputStream(file);
        p.store(fOut, "Favorite Things");
        fOut.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

}

于 2013-03-14T21:38:47.600 回答
-1

如果您只想覆盖 1 个道具,为什么不向您的 java 命令添加参数。无论您在属性文件中提供什么,它们都将被属性 args 覆盖。

java -Dyour.prop.to.be.overrided="value" -jar  your.jar
于 2020-07-16T10:15:30.933 回答