如何覆盖 .properties 中的一个属性而不覆盖整个文件?

发布于 2024-12-05 02:49:14 字数 567 浏览 1 评论 0原文

基本上,我必须通过 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();

Basically, I have to overwrite a certain property in a .properties file through a Java app, but when I use Properties.setProperty() and Properties.Store() it overwrites the whole file rather than just that one property.

I've tried constructing the FileOutputStream with append = true, but with that it adds another property and doesn't delete/overwrite the existing property.

How can I code it so that setting one property overwrites that specific property, without overwriting the whole file?

Edit: I tried reading the file and adding to it. Here's my updated code:

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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

如梦亦如幻 2024-12-12 02:49:15
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();
        }
    }
}
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();
        }
    }
}
橘香 2024-12-12 02:49:14

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

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

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


其他答案以各种形式建议了以下方法:

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

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

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


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

The Properties API doesn't provide any methods for adding/replacing/removing a property in the properties file. The model that the API supports is to load all of the properties from a file, make changes to the in-memory Properties object, and then store all of the properties to a file (the same one or a different one).

But the Properties API is not unusual in the respect. In reality, in-place updating of a text file is difficult to implement without rewriting the entire file. This difficulty is a direct consequence of the way that files / file systems are implemented by a modern operating system.

If you really need to do incremental updates, then you need to use some kind of database to hold the properties, not a ".properties" file.


Other Answers have suggested the following approach in various guises:

  1. Load properties from file into Properties object.
  2. Update Properties object.
  3. Save Properties object on top of existing file.

This works for some use-cases. However the load / save is liable to reorder the properties, remove embedded comments and white space. These things may matter1.

The other point is that this involves rewriting the entire properties file, which the OP is explicitly trying2 to avoid.


1 - If the API is used as the designers intended, property order, embedded comments, and so on wouldn't matter. But lets assume that the OP is doing this for "pragmatic reasons".
2 - Not that it is practical to avoid this; see earlier.

陈独秀 2024-12-12 02:49:14

您可以使用 Apache Commons 配置中的 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();

You can use PropertiesConfiguration from Apache Commons Configuration.

In version 1.X:

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

From version 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();
痴意少年 2024-12-12 02:49:14

我知道这是一个老问题,但这是工作代码(对问题中的代码进行了稍微修改,以防止在加载值之前删除它们):

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

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

props.setProperty("somekey", "somevalue");

FileOutputStream out = new FileOutputStream("file.properties");
props.store(out, null);
out.close();

I know this is an old question, but this is working code (slightly modified from the code in the question, to prevent the deletion of the values before we load them):

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

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

props.setProperty("somekey", "somevalue");

FileOutputStream out = new FileOutputStream("file.properties");
props.store(out, null);
out.close();
东北女汉子 2024-12-12 02:49:14

属性文件是为应用程序提供配置的一种简单方法,但不一定是进行编程的、特定于用户的自定义的好方法,正如您所发现的那样。

为此,我将使用 首选项 API。

Properties files are an easy way to provide configuration for an application, but not necessarily a good way to do programmatic, user-specific customization, for just the reason that you've found.

For that, I'd use the Preferences API.

烙印 2024-12-12 02:49:14

我执行以下方法:-

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

I do the following method:-

  1. Read the file and load the properties object
  2. Update or add new properties by using ".setProperty" method. (setProperty method is better than .put method as it can be used for inserting as well as updating the property object)
  3. Write the property object back to file to keep the file in sync with the change.
呆萌少年 2024-12-12 02:49:14
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", "[email protected]");
        props.setProperty("email.support_2", "[email protected]");

       // 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);
      }
   }
}

该程序的输出将是:

[email protected]
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", "[email protected]");
        props.setProperty("email.support_2", "[email protected]");

       // 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);
      }
   }
}

The output of the program would be:

[email protected]
故事↓在人 2024-12-12 02:49:14

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

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) {
        
    }
}

Please use just update file line instead using Properies e.g.

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) {
        
    }
}
提笔书几行 2024-12-12 02:49:14

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

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

If you just want to override 1 prop why not just add parameter to your java command. Whatever you provide in your properties file they will be overrided with properties args.

java -Dyour.prop.to.be.overrided="value" -jar  your.jar
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文