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

Java 如果存在命令行值,则覆盖属性文件,java,properties,command-line-arguments,Java,Properties,Command Line Arguments,我有一个程序,如果命令行不包含config.properties文件位置以外的任何参数,它将读取config.properties文件中的所有内容。下面是我的config.properties文件- NUMBER_OF_THREADS: 100 NUMBER_OF_TASKS: 10000 ID_START_RANGE: 1 TABLES: TABLE1,TABLE2 如果我像这样从命令提示符运行我的程序- java-jartest.jar“C:\\Test\\config.propertie

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

NUMBER_OF_THREADS: 100
NUMBER_OF_TASKS: 10000
ID_START_RANGE: 1
TABLES: TABLE1,TABLE2
如果我像这样从命令提示符运行我的程序-

java-jartest.jar“C:\\Test\\config.properties”

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

java-jar Test.jar“C:\\Test\\config.properties”10 100 2表1表2表3

然后它应该从参数中读取所有属性,并覆盖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-jartest.jar“C:\\Test\\config.properties”10 100

然后在我的程序中,它应该只覆盖
noOfThreads
noOfTasks
-

noOfThreads should be 10 instead of 100
noOfThreads should be 10 instead of 100
noOfTasks should be 100 instead of 10000
以及其他可能的用例

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

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文件。

而是创建一个循环

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
List paramNames=new ArrayList{“线程数”、“任务数”,
“ID\u开始\u范围”,“表”};//尝试重用属性文件中的名称
Map paramMap=新的HashMap();
...
//在此验证参数的长度
...
//您可以单独传递表名。你需要设法解决这个问题。
//当参数的数量等于参数名称的数量时,此实现将起作用
对于(int i=0;i
定义以下命令行输入时

java-jartest.jar“C:\\Test\\config.properties”10 100

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

为了解决这个问题,您可以在命令行中将这些属性和文件位置一起指定为系统属性,其他方面也有一个默认位置。例如:-

java-jar-Dconfig.file.location=“C:\\test\\config.properties”-DNUMBER\u OF_THREADS=10 test.jar

那么

  • 将文件属性读入
    属性
  • 迭代属性中的键并找到相应的
    System.getProperty()
  • 如果找到值,则覆盖属性中的相应条目
  • 这样,无论引入多少新属性,代码都将保持不变

    您可以更进一步,将所有这些封装在一个
    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);
      }
    }
    
    例子

    config.properties

    NUMBER_OF_THREADS=100
    NUMBER_OF_TASKS=10000
    ID_START_RANGE=1
    TABLES=TABLE1,TABLE2
    
    要覆盖
    线程数

    java-jar-Dconfig.file.location=“C:\\test\\config.properties”-DNUMBER\u OF_THREADS=10 test.jar

    将“线程数”读取为int的简短示例

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

    问问阿德尔。谢谢阿德尔的帮助。我没有使用JDK1.7,因此无法使用这些大括号:(同时,你能给我一个完整的流程,我应该把它放在那里,让它工作起来。谢谢你的帮助。TechGeeky:我已经替换了菱形操作符,所以你可以用Java 6来使用它。谢谢sgp15的建议。如果你能给我提供一个基于我的场景的示例,那么我将能够更好地理解。谢谢e help.+1单独用于-D选项。顺便说一句,您的getIntProperty()似乎已损坏。因此,我修复了它。如果您认为它实际上是正确的,欢迎您将其还原。