If I have the below property in my property file, how do I get the property key? I know how to get the value, but I am not sure how to get the key?
String myCountry="Australia";
I have this property along with others in my file. How do I get the key name (myCountry)? I would like to display it in System.out, so I need it, but I can't figure out how to get the key name, please help.
The point of a properties file is to associate configurable values with well-known keys. You should know the key and use it to find which configurable value has been associated with the key. Otherwise, a Properties object is a Map, and you can iterate through all the entries:
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
System.out.prinln(entry.getKey() + " = " + entry.getValue());
}
There is a method public Set<String> stringPropertyNames() in class java.util.Properties which is documented as:
Returns a set of keys in this property list where the key and its corresponding value are strings, including distinct keys in the default property list if a key of the same name has not already been found from the main properties list. Properties whose key or value is not of type String are omitted.
The returned set is not backed by the Properties object. Changes to this Properties are not reflected in the set, or vice versa.
Returns:
a set of keys in this property list where the key and its corresponding value are strings, including the keys in the default property list.
Why are you writing String myCountry="Australia"; in your properties file ? If you can simply keep like myCountry=Australia. And also no need to to write String .
All properties file values are String.
The java.util.Properties Class extends the java.util.HashTable Class, so has a keys() method. you can use this to retrieve a list of all the keys used in the file.
To printout a key for a given value something like this will work:
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
if(entry.getValue().equals("Australia")) {
System.out.prinln(entry.getKey() + " = " + entry.getValue());
}
}
This iterates through all the properties as key, value pairs until the pair with the correct value is found.
Also this might help:
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.Properties;
public class MainClass {
public static void main(String args[]) throws Exception {
Properties p = new Properties();
p.load(new FileInputStream("test.txt"));
Enumeration e = p.propertyNames();
for (; e.hasMoreElements();) {
System.out.println(e.nextElement());
}
}
}
Source: http://www.java2s.com/Tutorial/Java/0140__Collections/GettingakeyListfromProperties.htm
Related
I would like to edit a yaml in java , ( I'm editing BungeeCord config file to create a system that launches instance of bungeecord with a defined by user port ) but in a precise way , i need to write exactly this in the yaml file :
listeners:
- query_port: 25577
motd: '&1Another Bungee server'
tab_list: GLOBAL_PING
query_enabled: false
proxy_protocol: false
ping_passthrough: false
priorities:
- lobby
bind_local_address: true
host: 0.0.0.0:25577
max_players: 1
tab_size: 60
force_default_server: false
I did something very similar but there is a vertical bar that prevents BungeeCord from reading the file :
public class ProxyYaml {
HashMap<String, Object> entries = new HashMap<String, Object>();
public ProxyYaml() {
entries.put("query_port", 25577);
entries.put("motd", "Hey Guys");
entries.put("tab_list", "GLOBAL_PING");
entries.put("query_enabled", false);
entries.put("proxy_protocol", false);
entries.put("ping_passthrough", false);
entries.put("priorities", Arrays.asList("lobby"));
entries.put("bind_local_address", true);
entries.put("host", "0.0.0.0:25577");
entries.put("max_players", 1);
entries.put("tab_size", 60);
entries.put("force_default_server", false);
}
public ArrayList<String> getProperties() {
ArrayList<String> finalString = new ArrayList<String>();
for(String entry : entries.keySet()) {
finalString.add(entry + ": " + entries.get(entry).toString());
}
return finalString;
}
}
( I'm using SimpleYaml api but I can change the api if needed )
File propsProxyFile = new File(path + "config.yml");
YamlFile propsProxyYaml = new YamlFile(propsProxyFile);
try {
propsProxyYaml.load(propsProxyFile);
propsProxyYaml.set("listeners", Arrays.asList(new ProxyYaml().getProperties()));
propsProxyYaml.save(propsProxyFile);
} catch (IOException | InvalidConfigurationException e) {
System.out.println(MainNetwork.logo + "Can't load proxy properties file");
return;
}
There is the code output ( with the vertical bar ) :
listeners:
- |
query_port: 25577
motd: '&1Another Bungee server'
tab_list: GLOBAL_PING
query_enabled: false
proxy_protocol: false
ping_passthrough: false
priorities:
- lobby
bind_local_address: true
host: 0.0.0.0:25577
max_players: 1
tab_size: 60
force_default_server: false
What should I do please ?
The pipe character (|) starts a YAML block scalar. It means that all the following lines are a literal string and not subject to further YAML parsing.
There are lots of strange things happening in your code, let's go over them:
public ArrayList<String> getProperties() {
ArrayList<String> finalString = new ArrayList<String>();
for(String entry : entries.keySet()) {
finalString.add(entry + ": " + entries.get(entry).toString());
}
return finalString;
}
You are manually transforming a mapping into a list of strings here. Why do you do that? You expect the final YAML file to contain the key-value pairs as mapping, so you should not transform them into a list of strings.
Let's discuss what happens here with a quick example:
Assume we have this java Map:
Map<String, String> value = Map.of("foo", "bar");
If we directly serialize this to YAML, we would get
foo: bar
but if we pipe it through your method, we'll get
- "foo: bar"
i.e. a sequence of one scalar value – because we manually transformed the mapping entry into a string! This is not what you want.
propsProxyYaml.set("listeners", Arrays.asList(new ProxyYaml().getProperties()));
You call Arrays.asList on the return value of getProperties() which is of type ArrayList<String> so asList will return a value of type List<ArrayList<String>>, which has a single entry that is the list you built. It is unclear why you call Arrays.asList unless you want to have a list of lists. According to the desired YAML output, this is not what you want.
Now let's discuss what the set method does. I don't really know SimpleYAML and frankly, its documentation is horrible as it basically only consists of the autogenerated API docs. The first parameter of the method is named path, which implies that it is not a simple mapping key.
What apparently happens is that the List<ArrayList<String>> value is transformed into a YAML sequence with one scalar value, and that scalar value contains all the string values you produced, separated by newlines. Without proper documentation, it is impossible to say whether this is expected behavior or a bug. In any case, it makes no sense.
Now the actual YAML contains a mapping at its root with one entry, whose key is the scalar listeners. Its value is a list that contains another mapping. This means, the type you actually want to serialize is
Map<String, List<Map<String, Object>>>
I suggest that you simply build a value of this type and use the SnakeYAML API, which does have proper documentation on how its serialization system works. SimpleYAML uses SnakeYAML under the hood anyway, and there seems to be no reason to use a poorly documented API with surprising behavior instead of a well-documented one.
You can also create a custom Java class instead of using Maps. Then the keys would become class fields.
I have the below method, in which I am extracting the value from the entity and then setting it in map as a value of that map but my point is that for each key I am setting the value explicitly so if the count of keys grows that method code will also grow , can I make a common method based on approach Map.computeIfPresent, please advise how can I achieve both the things
private void setMap(AbcLoginDTO abcLoginDTO, Map<String, Object> getMap) {
getMap.put("XXNAME", abcLoginDTO.getUsername());
getMap.put("XX_ID", abcLoginDTO.getClientId());
getMap.put("RR_ID", abcLoginDTO.getUserId());
getMap.put("QQ_TIME", abcuserLoginDTO.getLocktime());
}
something like in this below approach I am thinking
static <E> void setIfPresent(Map<String, Object> map, String key, Consumer<E> setter, Function<Object, E> mapper) {
Object value = map.get(key);
if (value != null) {
setter.accept(mapper.apply(value));
}
}
but my point is that for each key I am setting the value explicitly so
if the count of keys grows that method code will also grow
You need to populate the Map with different values from the DTO, so you don't have other choices.
The method is long because you don't have a mapping between the key to add in the Map and the value to retrieve from the DTO.
You could write your code with a function such as :
static void setValueInMap(Map<String, Object> map, String key, Supplier<Object> mapper) {
map.put(key, mapper.get());
}
And use that :
Map<String, Object> map = ...;
AbcLoginDTO dto = ...;
setIfPresent(map, "keyUserName", dto::getUserName);
// and so for
But no real advantages.
Your second snippet has not at all relationship with the first one.
If i understand correctly, what you want to do is iterate over all of the object's members, get their value, and set them to a map according to their name. If so, then what you're looking for is called Reflection.
Every object can give you an array of its fields or methods (even private ones!) and then you can manipulate them using the Field / Method object.
Field[] members = AbcLoginDTO.class.getDeclaredFields();
Map<String, Object> values = new HashMap<>();
for(Field member : members) {
member.setAccessible(true);
values.put(member.getName(), member.get(abcLoginDTO));
}
What you end up with here, is a "Map representation" of your AbcLoginDTO instance. from here you can do with it what you want...
notice that i am "inspecting" the class itself in line 1, and then using the instance at line 6.
this code is not complete, but it's a start, and this can also be adapted to work for ANY object.
I don't know if I understood correctly, but if I did then that means all you need is a way to manually set different keys for the methods of your AbcLoginDTO class
If so then that can be done easily,
let's consider that your abcLoginDTO.getClientId() is always different for every AbcLoginDTO object:
private void setMap(AbcLoginDTO abcLoginDTO, Map<String, Object> getMap) {
getMap.put(Integer.toString(abcLoginDTO.getClientId())+"_NAME", abcLoginDTO.getUsername());
getMap.put(Integer.toString(abcLoginDTO.getClientId())+"_ID", abcLoginDTO.getClientId());
getMap.put(Integer.toString(abcLoginDTO.getClientId())+"_ID", abcLoginDTO.getUserId());
getMap.put(Integer.toString(abcLoginDTO.getClientId())+"_TIME", abcuserLoginDTO.getLocktime());
}
I have a HashMap with String as the key type and String[] as value type.
I want to be able to change part of the value (a String array).
I am storing files' contents using this HashMap by saving the file name as the key and its contents as the value (String[]).
I've succeeded in collecting all the data for this HashMap. I want the value
to be displayed in this way:
Key: alert
Value:
0-=Rule_Name,Configuration_Set_ID,Alert_UID,Headline,Create_DateTime
1-f5_high_compression_profile,,211,61b6cc42-0b32-4bd9-a3be-a98d7144ca85,Compression profile gzip level too high,1565003688537
2-f5_automap_enabled,407,0b380e7d-22f9-40c2-8277-3a5ed2ea7116,Automap enabled,1565003696956
I want to replace value of epochtime in the string to Date with this convention yyyy/MM/dd HHmmss for each record (epoch time may be different in the file).
public void createHashMapWithAlertCSVContent() throws Exception {
for(String item: lstServer) {
String[] contentCSVStr=
CmdHelper.Remote.File.cat(SERVER,INDENI_INSIGHT_PATH +
"/"+item).split("\n");
mapServer.put(FileUtil.removeExtension(item), contentCSVStr);
}
if(mapServer.containsKey("job")) {
mapServer.remove("job");
Assert.assertEquals(mapServer.size()-1, lstServer.size());
} else {
Assert.assertEquals(mapServer.size(), lstServer.size());
}
mapServer.entrySet().forEach(entry-> {
System.out.println(entry.getKey() + " " +
entry.getValue());
});
}
What I expected to happen was any entry of epoch time in the array of string would be replaced to yyyy/MM/dd HHmmss convention.
I have this string f5_high_compression_profile,,211,61b6cc42-0b32-4bd9-a3be-a98d7144ca85,Compression profile gzip level too high,1565003688537.
I want to change 1565003688537 to look like the yyyy/MM/dd HHmmss convention.
1565003688537 may not be the same value when I read the content of the CSV, so it has to be able to handle that.
I want to change each entry of ecpoh time into date format value.
You can just read the value by map.get(key) then edit it and the put it again with map.put(key, value).
If the value is of a muatable type, eg. String[] then you can just make modifications directly on this object, because the map is referencig to this object and not holding a copy.
eg.
String[] value = map.get(key);
value[0] = "new String";
If you want to change the size of the String[] then you need to create new list and put it under same key to replace the previous value, or you can change the type to use List instaed of String[] so it will be easier to modify it.
I have a properties (cant change this file) and it looks like:
aaa.bbb.ccc.first=my first value
aaa.bbb.ccc.second=my second value
aaa.bbb.ccc.third=my third value
If I need any value in java classes I use i18n.getText("aaa.bbb.ccc.first") but it works only for single value.
Problem is because I dont know:
-value's names
-how many values are in aaa.bbb.ccc.~
How is it possible to get list of value aaa.bbb.ccc~?
You could use a MapFilter. Use the MapFilter(Properties p, String prefix) constructor.
public void test() {
Properties props = new Properties();
props.put("aaa.bbb.ccc.first", "my first value");
props.put("aaa.bbb.ccc.second", "my second value");
props.put("aaa.bbb.ccc.third", "my third value");
props.put("Other.props", "others");
MapFilter<String> filtered = new MapFilter(props, "aaa.bbb.ccc.");
for (Map.Entry<String, String> e : filtered.entrySet()) {
System.out.println("Key: " + e.getKey() + " Value: " + e.getValue());
}
System.out.println(filtered);
}
Hash maps are not meant for the kind of lookup you want to do: Tries and radix trees are. There is an implementation of the Patricia trie data structure (i.e., binary radix trees) in Apache Commons Collections: Just create a trie from your Map<String, Whatever> (you have a nice constructor at the purpose) and with prefixMap("aaa.bbb.ccc") you obtain the submap of all the entries whose key have that prefix.
Properties has a method propertyNames(). You can use that to get all the keys then do whatever you want from there.
Suppose I have a JsonObject from javax named jsonObject, which looks like this: {"key":"value"}
How can I get the key name key?
I only find methods like getJsonString to get the key value value, but not the name of the key itself.
Background:
I have a Json Array, which contains key-value pairs. I want to know the name of the key on a specific index i.
Example:
[{"key1":"value0"},{"key1":"value1"},{"key2","value2"}]
key1 here is a success, key2 is a fail and has to be checked.
JsonObject implements Map<String, JsonValue>. You can call jsonObject.keySet() to access the keys, or call jsonObject.entrySet() to get a complete view of the object including both keys and values.
for (String key: jsonObject.keySet()) {
System.out.println(key);
}
In the context of the problem you described, it sounds like you'll want to validate that each array element contains an object with exactly one key-value pair. Perhaps something like this:
Set<Map.Entry<String, JsonValue>> kvPairs = jsonObject.entrySet();
if (kvPairs.size() == 1) {
for (Map.Entry<String, JsonValue> kvPair: kvPairs) {
if (kvPair.getKey().equals("key1")) {
// success
} else {
// error handling
}
}
} else {
// error handling
}