java 如果存在命令行值,则覆盖属性文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15469504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 19:42:56  来源:igfitidea点击:

Overwrite the properties file if command line value is present

javapropertiescommand-line-arguments

提问by arsenal

I have a program which will read everything from config.propertiesfile if command line does not contain any arguments apart from config.properties file location. Below is my config.properties file-

config.properties如果命令行不包含除 config.properties 文件位置之外的任何参数,我有一个程序将从文件中读取所有内容。下面是我的 config.properties 文件-

NUMBER_OF_THREADS: 100
NUMBER_OF_TASKS: 10000
ID_START_RANGE: 1
TABLES: TABLE1,TABLE2

If I am running my program from the command prompt like this-

如果我像这样从命令提示符运行我的程序 -

java -jar Test.jar "C:\\test\\config.properties"

java -jar Test.jar "C:\\test\\config.properties"

It should read all the four properties from the config.propertiesfile. But suppose if I am running my program like this-

它应该从config.properties文件中读取所有四个属性。但是假设如果我像这样运行我的程序 -

java -jar Test.jar "C:\\test\\config.properties" 10 100 2 TABLE1 TABLE2 TABLE3

java -jar Test.jar "C:\\test\\config.properties" 10 100 2 TABLE1 TABLE2 TABLE3

then it should read all the properties from the arguments and overwrite the properties in config.properties file.

然后它应该从参数中读取所有属性并覆盖 config.properties 文件中的属性。

Below is my code which is working fine in this scenario-

下面是我在这种情况下运行良好的代码-

public static void main(String[] args) {

        try {

            readPropertyFiles(args);

        } catch (Exception e) {
            LOG.error("Threw a Exception in" + CNAME + e);
        }
    }

    private static void readPropertyFiles(String[] args) throws FileNotFoundException, IOException {

        location = args[0];

        prop.load(new FileInputStream(location));

        if(args.length >= 1) {
            noOfThreads = Integer.parseInt(args[1]);
            noOfTasks = Integer.parseInt(args[2]);
            startRange = Integer.parseInt(args[3]);

            tableName = new String[args.length - 4];
            for (int i = 0; i < tableName.length; i++) {
                tableName[i] = args[i + 4];
                tableNames.add(tableName[i]);
            }
        } else {
            noOfThreads = Integer.parseInt(prop.getProperty("NUMBER_OF_THREADS").trim());
            noOfTasks = Integer.parseInt(prop.getProperty("NUMBER_OF_TASKS").trim());
            startRange = Integer.parseInt(prop.getProperty("ID_START_RANGE").trim());
            tableNames = Arrays.asList(prop.getProperty("TABLES").trim().split(","));
        }

        for (String arg : tableNames) {

            //Some Other Code

        }
    }   

Problem Statement:-

问题陈述:-

Now what I am trying to do is- Suppose if any person is running program like this

现在我想做的是 - 假设是否有人正在运行这样的程序

java -jar Test.jar "C:\\test\\config.properties" 10

java -jar Test.jar "C:\\test\\config.properties" 10

then in my program, it should overwrite noOfThreadsonly-

然后在我的程序,它应该覆盖noOfThreadsonly-

noOfThreads should be 10 instead of 100

And suppose if that person is running program like this-

假设那个人正在运行这样的程序——

java -jar Test.jar "C:\\test\\config.properties" 10 100

java -jar Test.jar "C:\\test\\config.properties" 10 100

then in my program, it should overwrite noOfThreadsand noOfTasksonly-

然后在我的程序,它应该覆盖noOfThreadsnoOfTasksonly-

noOfThreads should be 10 instead of 100
noOfTasks should be 100 instead of 10000

And possible other use cases as well.

以及可能的其他用例。

Can anyone suggest me how to achieve this scenario? Thanks for the help

谁能建议我如何实现这种情况?谢谢您的帮助

采纳答案by Adeel Ansari

Create a loop, instead.

而是创建一个循环。

List<String> paramNames = new ArrayList<String>{"NUMBER_OF_THREADS", "NUMBER_OF_TASKS", 
            "ID_START_RANGE", "TABLES"}; // Try to reuse the names from the property file
Map<String, String> paramMap = new HashMap<String, String>();
...
// Validate the length of args here
...
// As you table names can be passed separately. You need to handle that somehow. 
// This implementation would work when number of args will be equal to number of param names
for(int i = 0; i< args.length; i++) {
   paramMap.put(paramNames[i], args[i]); 
}

props.putAll(paramMap);
... // Here props should have it's values overridden with the ones provided

回答by sgp15

When defining command line input as follows

如下定义命令行输入时

java -jar Test.jar "C:\\test\\config.properties" 10 100

java -jar Test.jar "C:\\test\\config.properties" 10 100

It means one must always provide noOfThreadsto override noOfTasks.

这意味着必须始终提供noOfThreads覆盖noOfTasks.

To solve this you could specify these as system properties on command line along with file location which other wise has a default location too. For example: -

为了解决这个问题,您可以在命令行上将这些指定为系统属性以及文件位置,否则该文件位置也具有默认位置。例如: -

java -jar -Dconfig.file.location="C:\\test\\config.properties" -DNUMBER_OF_THREADS=10 Test.jar

java -jar -Dconfig.file.location="C:\\test\\config.properties" -DNUMBER_OF_THREADS=10 Test.jar

Then.

然后。

  1. Read file properties into Properties.
  2. Iterate over keys in the properties and find corresponding System.getProperty().
  3. If value is found override corresponding entry in the properties.
  1. 将文件属性读入Properties.
  2. 迭代属性中的键并找到相应的System.getProperty().
  3. 如果找到值,则覆盖属性中的相应条目。

This way no matter how many new properties you introduce your code will always remain same.

这样无论您引入多少新属性,您的代码都将始终保持不变。

You can go step further and encapsulate all of this in a PropertyUtilthat also provide utility methods like getIntProperty(), getStringProperty()etc.

你可以走得更远一步,封装了所有的这一场PropertyUtil还提供了实用的方法,如getIntProperty()getStringProperty()等。

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class PropertyUtil {

  private static final String DEFAULT_CONFIG_FILE_LOCATION = "config.properties";

  private String configFileLocation;

  private Properties properties;

  public PropertyUtil() throws IOException {

    this(DEFAULT_CONFIG_FILE_LOCATION);
  }

  public PropertyUtil(String configFileLocation) throws IOException {

    this.configFileLocation = configFileLocation;
    this.properties = new Properties();
    init();
  }

  private void init() throws IOException {

    properties.load(new FileInputStream(this.configFileLocation));

    for (Object key : this.properties.keySet()) {

      String override = System.getProperty((String) key);

      if (override != null) {

        properties.put(key, override);
      }
    }
  }

  public int getIntProperty(String key) {

    return this.properties.contains(key) ? Integer.parseInt(properties.get(key)) : null;
  }

  public String getStringProperty(String key) {

    return (String) this.properties.get(key);
  }
}

Examples.

例子。

config.properties

config.properties

NUMBER_OF_THREADS=100
NUMBER_OF_TASKS=10000
ID_START_RANGE=1
TABLES=TABLE1,TABLE2

To override NUMBER_OF_THREADS.

覆盖NUMBER_OF_THREADS.

java -jar -Dconfig.file.location="C:\\test\\config.properties" -DNUMBER_OF_THREADS=10 Test.jar

java -jar -Dconfig.file.location="C:\\test\\config.properties" -DNUMBER_OF_THREADS=10 Test.jar

Short hand example to read 'NUMBER_OF_THREADS' as int.

将 'NUMBER_OF_THREADS' 读为 int 的简写示例。

new PropertyUtil(System.getProperty("config.file.location")).getIntProperty("NUMBER_OF_THREADS");

回答by Xavier DSouza

Properties properties = new Properties();
properties.load(new FileInputStream("C:\test\config.properties"));

Then as per your command line arguments set the individual properties as :

然后根据您的命令行参数将各个属性设置为:

setProperty("NUMBER_OF_THREADS", args[1]);
setProperty("NUMBER_OF_TASKS", args[2]);

This won't overwrite the existing config.properties file.

这不会覆盖现有的 config.properties 文件。