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

发布于 2024-12-10 06:48:14 字数 697 浏览 0 评论 0原文

我将应用程序设置存储在我在 Ant 和 Java 应用程序中使用的属性文件中。也许这不是一个好的做法,但我发现它非常方便避免重复。该文件包含以下变量:

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

以便其他人可以在 *nix 系统上运行该程序,前提是他们的主目录中具有有用的文件夹。

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

我在 Ant 中使用以下代码加载 props:

   <loadproperties srcFile="myProps.properties"/>

在 Java 应用程序中:

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

我遗漏了什么吗?也许有比 load() 更好的方法在 Java 应用程序中加载属性吗?

I'm storing my app settings in properties file that I use in Ant and in the Java app. Maybe it's not good pratice, but I find it very handy to avoid duplications. The file contains variables such as:

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

So that other people can run the program on *nix systems, provided that they have the usefulstuff folder in their home directory.

Now, the fascinating thing is that this properties file works fine in Ant (the variable gets resolved to /home/username), while when I load the same file directly in the Java app, I get a string containing ${user.home}/usefulstuff, which is not very useful indeed.

I load the props with this code in Ant:

   <loadproperties srcFile="myProps.properties"/>

And in the Java app:

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

Am I missing anything? Maybe is there a better way to load properties in a Java app than load()?

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

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

发布评论

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

评论(2

焚却相思 2024-12-17 06:48:14

我不认为这在 Ant 中起作用是特别“迷人”的 - Ant 是故意这样做的

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

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

如果您想要相同的行为,则需要实现相同的逻辑。您可以直接使用 Ant 中的类,只要它们能够满足您的要求,并且您愿意提供相关的二进制文件(并遵守许可证)。

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

I don't think it's particularly "fascinating" that this works in Ant - Ant is deliberately written to do so:

Properties are key-value-pairs where Apache Ant tries to expand ${key} to value at runtime.

and

Ant provides access to all system properties as if they had been defined using a <property> task. For example, ${os.name} expands to the name of the operating system.

If you want the same behaviour, you'll need to implement the same sort of logic. It's possible that you could use the classes from Ant directly, if they do what you want - and if you're happy to ship the relevant binaries (and abide by the licence).

Otherwise, you might want to use a regular expression to find all the matches - or (probably simpler) iterate over all of the system properties and do a simple replacement on them.

-黛色若梦 2024-12-17 06:48:14

正如 Jon 所说,自己编写属性处理应该很简单。例如:

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

As Jon said, it should be straighforward to write the property handling yourself. For eg:

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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文