包含美元分隔变量的Java属性

时间:2011-10-14 19:04:10

标签: java variables ant properties dollar-sign

我将我的应用设置存储在我在Ant和Java应用中使用的属性文件中。也许这不是很好的实践,但我觉得避免重复是非常方便的。该文件包含变量,如:

usefulstuff.dir = ${user.home}/usefulstuff

这样其他人就可以在* nix系统上运行该程序,只要他们的主目录中有有用的资料文件夹。

现在,令人着迷的是这个属性文件在 Ant (变量被解析为/home/username)中运行良好,而当我直接在Java应用程序中加载相同的文件时,我得到一个包含${user.home}/usefulstuff的字符串,这确实不是很有用。

我在Ant中使用此代码加载道具:

   <loadproperties srcFile="myProps.properties"/>

在Java应用程序中:

    FileInputStream ins = new FileInputStream(propFilePath);
    myProps.load(ins);
    ins.close();

我错过了什么吗?也许有更好的方法在Java应用程序中加载属性而不是load()

2 个答案:

答案 0 :(得分:6)

我认为这在Ant中起作用并不特别“迷人” - Ant is deliberately written to do so

  

属性是键值对,其中Apache Ant尝试在运行时将${key}扩展为值。

  

Ant提供对所有系统属性的访问,就像使用<property>任务定义它们一样。例如,$ {os.name}扩展为操作系统的名称。

如果你想要相同的行为,你需要实现相同的逻辑。您可以直接使用Ant中的类,如果他们按照您的意愿行事 - 并且您很乐意发送相关的二进制文件(并遵守许可证)。

否则,您可能希望使用正则表达式来查找所有匹配项 - 或者(可能更简单)迭代所有系统属性并对它们进行简单替换。

答案 1 :(得分:2)

正如乔恩所说,自己编写财产处理应该是直截了当的。例如:

import java.util.*;

public class PropertiesTest
{
    public static void main(String[] args)
    {
        Properties props = new Properties();
        props.setProperty("foo", "foo/${os.name}/baz/${os.version}");
        props.setProperty("bar", "bar/${user.country}/baz/${user.country}");

        System.out.println("BEFORE:");
        printProperties(props);

        resolveSystemProperties(props);

        System.out.println("\n\nAFTER:");
        printProperties(props);
    }

    static void resolveSystemProperties(Properties props)
    {
        Map<String, String> sysProps = readSystemProperties();
        Set<String> sysPropRefs = sysProps.keySet();

        Enumeration names = props.propertyNames();
        while (names.hasMoreElements())
        {
            String name = (String) names.nextElement();
            String value = props.getProperty(name);
            for (String ref : sysPropRefs)
            {
                if (value.contains(ref))
                {
                    value = value.replace(ref, sysProps.get(ref));
                }
            }
            props.setProperty(name, value);
        }
    }

    static Map<String, String> readSystemProperties()
    {
        Properties props = System.getProperties();
        Map<String, String> propsMap = 
            new HashMap<String, String>(props.size());

        Enumeration names = props.propertyNames();
        while (names.hasMoreElements())
        {
            String name = (String) names.nextElement();
            propsMap.put("${" + name + "}", props.getProperty(name));
        }
        return propsMap;
    }

    static void printProperties(Properties props)
    {
        Enumeration names = props.propertyNames();
        while (names.hasMoreElements())
        {
            String name = (String) names.nextElement();
            String value = props.getProperty(name);
            System.out.println(name + " => " + value);
        }
    }
}