How to store an array in a Java properties file
Asked Answered
H

10

64

I'm currently making a .properties file that needs to be loaded and transformed into an array.
There is a possibility of anywhere from 0-25 of each of the property keys to exist.

I tried a few implementations but I'm just stuck at doing this cleanly.
Anyone have any ideas?

foo.1.filename=foo.txt
foo.1.expire=200

foo.2.filename=foo2.txt
foo.2.expire=10

etc more foo's

bar.1.filename=bar.txt
bar.1.expire=100

Where I'll assemble the filename/expire pairings into a data object, as part of an array for each parent property element like foo[myobject]

Formatting of the properties file can change, I'm open to ideas.

Heliotype answered 10/8, 2011 at 17:56 Comment(4)
I'm not totally clear on what you are doing, but does simply putting the properties into a Map work? It allows to you do if(foo.has('filename')), and to store/load, you just (de)serialize it...Pulverulent
Can you create classes containing every property that you might use in the .properties file, or are some properties going to be dynamic?Funnyman
@Funnyman - I've already got my class which holds filename + expire attrs, and methods, and I create new objects out of it. Are you suggesting maybe adding in a "type" attribute to it, to hold the "foo"s and "bar"s? ... Could work, i'll hack at it...Heliotype
I think a data file (like a .csv) would be easier. Properties are not really designed for this.Zosima
K
13

Either define a delimiter that will not be a potential value or learn to use XML.

If you still insist on using properties use one of the methods that will return a list of all keys. Your key appears to have three parts a group identifier (foo, bar) an index (1, 2) and then an element name (filename, expire). Get all the keys break them into their component parts. Create a List for each type of identifier, when processing the list use the identifier to determine which List to add to. Create you paired elements as you said and simply add to the list! If the index order is important either add that as a field to your paired elements or sort the keys before processing.

Killerdiller answered 10/8, 2011 at 18:27 Comment(5)
Use XML or deal with the painLemuellemuela
I abandoned that properties format and used xml. Much cleaner. More extensible for the future. Thank you for pushing me in the right direction.Heliotype
God, I love this answer, but unfortunately, some of us are strapped by bureaucracy and/or 'managerial limitations' which demand the use of .properties instead of .xml. I won't describe my current position, but, you know. (Also, necromancy.)Katz
I don't agree. I use both JSON and XML. As long as there is no "real" standard for json schemes I prefer XML for complex configurations. When you work on something as a team, and you're burdened with the maintaince and ongoing development based on it than a proper schema definition is priceless. No constraints means alot of headaches and discussion about how to do stuff. Or even worse, no discussion , anyone will implement whatever they want that fits their needs and you will quickly end up in a configuration hell. Autocompletion on somebody else his configuration files is also nice to have.Carrara
Json is so nulties, use Yaml!Decalescence
G
46

I can suggest using delimiters and using the

String.split(delimiter)

Example properties file:

MON=0800#Something#Something1, Something2

prop.load(new FileInputStream("\\\\Myseccretnetwork\\Project\\props.properties"));
String[]values = prop.get("MON").toString().split("#");

Hope that helps

Gridiron answered 4/7, 2012 at 2:3 Comment(2)
Simple and easy. PerfectLigure
But problem with this approach is that data in properties file should be in one line.Poston
L
13

Didn't exactly get your intent. Do check Apache Commons configuration library http://commons.apache.org/configuration/

You can have multiple values against a key as in key=value1,value2 and you can read this into an array as configuration.getAsStringArray("key")

Lunkhead answered 10/8, 2011 at 18:3 Comment(3)
I'm trying to avoid that, as in the very near forseeable future, the fields will contain , ; :Heliotype
Thanks Venu K. This might not be what yep needed but it is what I needed.Forklift
Good suggestion, this approach is quite helpful, thank you.Musk
K
13

Either define a delimiter that will not be a potential value or learn to use XML.

If you still insist on using properties use one of the methods that will return a list of all keys. Your key appears to have three parts a group identifier (foo, bar) an index (1, 2) and then an element name (filename, expire). Get all the keys break them into their component parts. Create a List for each type of identifier, when processing the list use the identifier to determine which List to add to. Create you paired elements as you said and simply add to the list! If the index order is important either add that as a field to your paired elements or sort the keys before processing.

Killerdiller answered 10/8, 2011 at 18:27 Comment(5)
Use XML or deal with the painLemuellemuela
I abandoned that properties format and used xml. Much cleaner. More extensible for the future. Thank you for pushing me in the right direction.Heliotype
God, I love this answer, but unfortunately, some of us are strapped by bureaucracy and/or 'managerial limitations' which demand the use of .properties instead of .xml. I won't describe my current position, but, you know. (Also, necromancy.)Katz
I don't agree. I use both JSON and XML. As long as there is no "real" standard for json schemes I prefer XML for complex configurations. When you work on something as a team, and you're burdened with the maintaince and ongoing development based on it than a proper schema definition is priceless. No constraints means alot of headaches and discussion about how to do stuff. Or even worse, no discussion , anyone will implement whatever they want that fits their needs and you will quickly end up in a configuration hell. Autocompletion on somebody else his configuration files is also nice to have.Carrara
Json is so nulties, use Yaml!Decalescence
P
8

Use YAML files for properties, this supports properties as an array.

Quick glance about YAML:

A superset of JSON, it can do everything JSON can + more

  1. Simple to read
  2. Long properties into multiline values
  3. Supports comments
  4. Properties as Array
  5. YAML Validation
Purdah answered 16/2, 2018 at 7:7 Comment(3)
Although I love this answer I must lament that java doesn't have built-in YAML processing last time I checked.Ritual
Yes, but if in case using Spring boot application, it already packed with 'Snakeyaml' dependency which is a YAML processor.Purdah
That's actually pretty good to know. We are quite restricted as to which software we can use but we just got Spring Boot approved. Thanks for the info!Ritual
I
7

I have custom loading. Properties must be defined as:

key.0=value0
key.1=value1
...

Custom loading:

/** Return array from properties file. Array must be defined as "key.0=value0", "key.1=value1", ... */
public List<String> getSystemStringProperties(String key) {

    // result list
    List<String> result = new LinkedList<>();

    // defining variable for assignment in loop condition part
    String value;

    // next value loading defined in condition part
    for(int i = 0; (value = YOUR_PROPERTY_OBJECT.getProperty(key + "." + i)) != null; i++) {
        result.add(value);
    }

    // return
    return result;
}
Isometrics answered 21/7, 2016 at 14:23 Comment(0)
C
4

I highly recommend using Apache Commons (http://commons.apache.org/configuration/). It has the ability to use an XML file as a configuration file. Using an XML structure makes it easy to represent arrays as lists of values rather than specially numbered properties.

Ceja answered 10/8, 2011 at 18:47 Comment(0)
S
3

here is another way to do by implementing yourself the mechanism. here we consider that the array should start with 0 and would have no hole between indice

    /**
     * get a string property's value
     * @param propKey property key
     * @param defaultValue default value if the property is not found
     * @return value
     */
    public static String getSystemStringProperty(String propKey,
            String defaultValue) {
        String strProp = System.getProperty(propKey);
        if (strProp == null) {
            strProp = defaultValue;
        }
        return strProp;
    }

    /**
     * internal recursive method to get string properties (array)
     * @param curResult current result
     * @param paramName property key prefix
     * @param i current indice
     * @return array of property's values
     */
    private static List<String> getSystemStringProperties(List<String> curResult, String paramName, int i) {
        String paramIValue = getSystemStringProperty(paramName + "." + String.valueOf(i), null);
        if (paramIValue == null) {
            return curResult;
        }
        curResult.add(paramIValue);
        return getSystemStringProperties(curResult, paramName, i+1);
    }

    /**
     * get the values from a property key prefix
     * @param paramName property key prefix
     * @return string array of values
     */
    public static String[] getSystemStringProperties(
            String paramName) {
        List<String> stringProperties = getSystemStringProperties(new ArrayList<String>(), paramName, 0);
        return stringProperties.toArray(new String[stringProperties.size()]);
    }

Here is a way to test :

    @Test
    public void should_be_able_to_get_array_of_properties() {
        System.setProperty("my.parameter.0", "ooO");
        System.setProperty("my.parameter.1", "oO");
        System.setProperty("my.parameter.2", "boo");
        // WHEN 
        String[] pluginParams = PropertiesHelper.getSystemStringProperties("my.parameter");

        // THEN
        assertThat(pluginParams).isNotNull();
        assertThat(pluginParams).containsExactly("ooO","oO","boo");
        System.out.println(pluginParams[0].toString());
    }

hope this helps

and all remarks are welcome..

Sightly answered 4/7, 2014 at 10:12 Comment(0)
N
0

As user 'Skip Head' already pointed out, csv or a any table file format would be a better fitt in your case.

If it is an option for you, maybe this Table implementation might interest you.

Napiform answered 10/8, 2011 at 18:42 Comment(0)
H
-1

I'd suggest having the properties file, reference a CSV file. Then parse the CSV file into a collection/array etc instead. Properties file seems wrong fit for this kind of data.

Hospitalet answered 1/10, 2021 at 13:58 Comment(0)
H
-6

Actually all answers are wrong

Easy: foo.[0]filename

Hallway answered 21/5, 2020 at 7:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.