【问题标题】:Overwrite the properties file if command line value is present如果存在命令行值,则覆盖属性文件
【发布时间】:2013-03-06 08:34:38
【问题描述】:

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

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

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

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

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

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

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

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

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

        }
    }   

问题陈述:-

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

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

那么在我的程序中,它应该只覆盖noOfThreads-

noOfThreads should be 10 instead of 100

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

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

那么在我的程序中,它应该只覆盖noOfThreadsnoOfTasks-

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

还有其他可能的用例。

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

【问题讨论】:

    标签: java properties command-line-arguments


    【解决方案1】:

    如下定义命令行输入时

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

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

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

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

    那么。

    1. 将文件属性读入Properties
    2. 遍历属性中的键,找到对应的System.getProperty()
    3. 如果找到值,则覆盖属性中的相应条目。

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

    您可以更进一步,将所有这些封装在 PropertyUtil 中,该 getIntProperty() 还提供实用方法,例如 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);
      }
    }
    

    示例。

    config.properties

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

    覆盖NUMBER_OF_THREADS

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

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

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

    【讨论】:

    • 感谢 sgp15 的建议。如果您可以在我的场景中为我提供一个示例基础,那么我将能够更好地理解。感谢您的帮助。
    • +1 仅用于 -D 选项。顺便说一句,你的 getIntProperty() 似乎坏了。所以,我修好了。如果您认为它实际上是正确的,欢迎您恢复它。
    【解决方案2】:

    改为创建一个循环。

    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
    

    【讨论】:

    • 问阿德尔。感谢阿德尔的帮助。我没有使用 JDK1.7,所以不能使用这些大括号。 :( 你也可以给我完整的流程,我应该把它放在哪里让这个东西工作。谢谢你的帮助。
    • TechGeeky:我已经替换了菱形运算符,所以你可以在 Java 6 中使用它。
    【解决方案3】:
    Properties properties = new Properties();
    properties.load(new FileInputStream("C:\\test\\config.properties"));
    

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

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

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

    【讨论】:

      猜你喜欢
      • 2015-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 2012-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多