如何在不覆盖整个文件的情况下覆盖.properties中的一个属性?

时间:2011-09-18 13:55:30

标签: java properties fileoutputstream

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

我尝试使用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();

9 个答案:

答案 0 :(得分:19)

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

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

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


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

  1. 将文件中的属性加载到Properties对象。
  2. 更新Properties对象。
  3. Properties对象保存在现有文件之上。
  4. 这适用于某些用例。但是,加载/保存可能会重新排序属性,删除嵌入的注释和空格。这些事情可能重要 1

    另一点是,这涉及重写整个属性文件,OP明确试图避免这种情况。


    1 - 如果API被用作设计者的意图,属性顺序,嵌入式注释等将不重要。但我们假设OP是出于“务实的原因”这样做的。

答案 1 :(得分:13)

您可以使用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();

答案 2 :(得分:3)

另一个答案提醒我Apache Commons Configuration库,特别是功能PropertiesConfigurationLayout

这允许(或多或少)保留原始布局,注释,排序等。

答案 3 :(得分:1)

属性文件是为应用程序提供配置的简单方法,但不一定是进行程序化,用户特定自定义的好方法,只是因为您找到了。

为此,我使用Preferences API。

答案 4 :(得分:1)

我采用以下方法: -

  1. 读取文件并加载属性对象
  2. 使用&#34; .setProperty&#34;更新或添加新属性方法。 (setProperty方法优于.put方法,因为它可以用于插入以及更新属性对象)
  3. 将属性对象写回文件,以使文件与更改保持同步。

答案 5 :(得分:0)

import java.io.*;
import java.util.*;
class 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();
        }

    }
}

答案 6 :(得分: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

答案 7 :(得分:0)

如果您只想覆盖1个prop,为什么不直接在Java命令中添加参数。无论您在属性文件中提供什么内容,都将使用属性args覆盖它们。

java -Dyour.prop.to.be.overrided="value" -jar  your.jar

答案 8 :(得分:-1)

是的,这是可能的。如果您不想从属性文件中删除您的内容。只需从文件中读取并替换字符串即可。

    String file="D:\\path of your file\abc.properties";     
    Path path = Paths.get(file);
    Charset charset = StandardCharsets.UTF_8;

    String content = new String(Files.readAllBytes(path), charset);
    content = content.replaceAll("name=anything", "name=anything1");
    Files.write(path, content.getBytes(charset));

上述代码不会删除文件中的内容。它只是替换文件中的部分内容。