Best way to get value from java string

If I get a string containing comma-separated key-value pairs, such as

seller=1000,country="canada",address="123 1st st" , etc.

There seems to be a better way than parsing and then repeating.

What is the best way to return a value from this string based on a key name in Java?

0
source share
7 answers

You can create your own CSV parser, this is not very difficult, but there are a few corner cases to make sure that, of course, you are using the standard CSV format.

But why reinvent the wheel ...

You can try to find a CSV parser, for example

There are others, look around, I'm sure that you will find one that suits you.

+2
source

Since release 10, Google Guava has provided the MapSplitter class, which does just such things:

 Map<String, String> params = Splitter .on(",") .withKeyValueSeparator("=") .split("k1=v1,k2=v2"); 
+7
source

You must first use the CSV parsing library to parse comma separated values. Correct Analysis of CSV data is not as trivial as it seems at first glance. There are many good arguments not to reinvent this wheel.

It will also validate your code in the future and be a code that you do not need to test or maintain.

I know that the temptation to do something like data.split(','); strong, but this is a fragile and fragile decision. For one example, what if any of the values ​​contains ".".

The second thing you need to do is parse the pairs. And again, the temptation to use String.split("="); will be strong, but it can be brittle and brittle if the right side = has = in it.

I am not a blind supporter of regular expressions, but I use them with restraint, they can only be the right tool for the job. Here is a regular expression for parsing name value pairs.

Regular expression ^ (. *) \ S? = \ s? ("? ([^"] *) "? |" (. *) ") $ , click on the regular expression to test it interactively. This works even for the multiple double quotes on the right side of the name value pair.

This will only correspond to what is to the left of the first = and everything else on the right side, and separate the optional " from the string values, while maintaining the numbers that coincide with the non-cyclic values.

List<String> list of encoded name value pairs specified.

 final Pattern p = Pattern.compile("^(.*)\s?=\s?("?([^"]*)"?|"(.*)")$"); final Map<String, String> map = new HashMap<String, String>(list.size()); for (final String nvp : list) { final Matcher m = p.matcher(nvp); m.matches(); final String name = m.group(1); final String value = m.group(2); System.out.format("name = %s | value = %s\n", name, value); } 
0
source

To separate the line with commas, other posters are correct. It is best to use the CSV parser (native or OTS). Considering things like commas inside quotation marks, etc., can lead to many unresolved issues.

Once you have every single token in the form:

 key = "value" 

I think it's easy enough to find the first index '=' . Then the part before that will be the key, and the part after that will be the value. Then you can save them in Map<String, String> . This assumes that your keys will be fairly simple and not contain = in them, etc. Sometimes it’s enough to go a simple route if you can limit the scope of the problem.

0
source

Usually you need to parse a string on a map because you will pull out different values, maybe several times, so it often makes sense to pay the cost of the parsing.

If not, then this is how I solved the problem (assuming you want to distinguish between int and String values) .:

 public Object pullValue(String pairs, String key) { boolean returnString = false; int keyStart = pairs.indexOf(key + "="); if (keyStart < 0) { logger.error("Key " + key + " not found in key-value pairs string"); return null; } int valueStart = keyStart + key.length() + 1; if (pairs.charAt(valueStart) == '"') { returnString = true; valueStart++; // Skip past the quote mark } int valueEnd; if (returnString) { valueEnd = pairs.indexOf('"', valueStart); if (valueEnd < 0) { logger.error("Unmatched double quote mark extracting value for key " + key) } return pairs.substring(valueStart, valueEnd); } else { valueEnd = pairs.indexOf(',', valueStart); if (valueEnd < 0) { // If this is the last key value pair in string valueEnd = pairs.length(); } return Integer.decode(pairs.substring(valueStart, valueEnd)); } } 

Note that this solution does not include spaces between the key, the equal sign, and the value. If possible, you will need to create code to move the line between them.

Another solution is to use a regular expression parser. You could do something like (this is untested):

 Pattern lookingForString = Pattern.compile(key + "[ \t]*=[ \t]*[\"]([^\"]+)[\"]"); Pattern lookingForInt = Pattern.compile(key + "[ \t]*=[ \t]*([^,]+)"); Matcher stringFinder = lookingForString.matcher(pairs); Matcher intFinder = lookingForInt.matcher(pairs); if (stringFinder.find()) { return stringFinder.group(1); } else if (intFinder.find()) { return Integer.decode(intFinder.group(1)); } else { logger.error("Could not extract value for key " + key); return null; } 

NTN

0
source

If you just want to get one value from such a string, you can use the String indexOf () and substring () methods:

 String getValue(String str, String key) { int keyIndex = str.indexOf(key + "="); if(keyIndex == -1) return null; int startIndex = str.indexOf("\"", keyIndex); int endIndex = str.indexOf("\"", startIndex); String value = str.substring(startIndex + 1, endIndex); return value; } 
0
source

Use String.split(yourdata, ',') and you will get String[] . Then do String.split(String[i],"=") , for each record, to separate the property and values.

Ideally, you should move this data to an instance of the Properties object. Then you can easily save / load it from XML. It has useful methods.

REM: I assume that you are smart enough to understand that this solution will not work if the values ​​contain a separator (i.e. a comma) in them ...

-1
source

All Articles