5

Having an issue where I have a java string:

String aString="name==p==?header=hello?aname=?????lname=lastname";

I need to split on question marks followed by equals.

The result should be key/value pairs:

name = "=p=="
header = "hello"
aname = "????"
lname = "lastname"

The problem is aname and lname become:

name = ""
lname = "????lname=lastname"

My code simply splits by doing aString.split("\\?",2)
which will return 2 strings.One contains a key/value pair and the second string contains the rest of the string. If I find a question mark in the string, I recurse on the second string to further break it down.

private String split(String aString)
 {
    System.out.println("Split: " + aString);
    String[] vals = aString.split("\\?",2);
    System.out.println("  - Found: " + vals.length);
    for ( int c = 0;c<vals.length;c++ )
       {
        System.out.println("  - "+ c + "| String: [" + vals[c] + "]" );
        if(vals[c].indexOf("?") > 0 )
          {
            split(vals[c]);
           }
        }
    return ""; // For now return nothing...
 }

Any ideas how I could allow a name of ?
Disclaimer: Yes , My Regex skills are very low, so I don't know if this could be done via a regex expression.

Jay
  • 1,317
  • 4
  • 16
  • 40
Multiplexor
  • 326
  • 1
  • 3
  • 13
  • 1
    Why is `p` not extracted as a key? – Evan Knowles May 16 '14 at 13:15
  • @Evan has a point. Do you know the keys (name, header, aname, lname) are always the same or come from a specific set? – chickenpie May 16 '14 at 13:22
  • Eventually it will be. For now, I was trying to split on the question marks. when I split on those, then I wind up with a string "name==p==" which I'll then split("\\=",2) and it gets me the key/value pair – Multiplexor May 16 '14 at 13:25
  • Hmmm chickenpie... I get what you're saying... ie: I could do something like extract values by reading upto the next key. – Multiplexor May 16 '14 at 13:26
  • The problem is your input. You should not use characters which are also special characters (`=` and `?` in your case). If you need these characters as key names or values, you should escape them, e.g. `name==p==?header=hello?aname=?????lname=lastname` – Absurd-Mind May 16 '14 at 13:38
  • @Absurd: I totally agree... just spoke with team lead and we agreed to throw an exception if someone enters a name with question marks. It's a start lol – Multiplexor May 16 '14 at 13:43
  • @Multiplexor What? If you are able to raise an Exception on input, you should also be able to encode your URLs correctly (i assume these are URL strings). See [URLEncoder.encode()](http://docs.oracle.com/javase/6/docs/api/java/net/URLEncoder.html#encode%28java.lang.String,%20java.lang.String%29) and [this question](http://stackoverflow.com/questions/10786042/java-url-encoding) for further information on that. – Absurd-Mind May 16 '14 at 13:48

4 Answers4

8

You can let regex do all the heavy lifting, first splitting your string up into pairs:

String[] pairs = aString.split("\\?(?!\\?)");

That regex means "a ? not followed by a ?", which gives:

[name==p==, header=hello, aname=????, lname=lastname]

To then also split the results into name/value, split only the first "=":

String[] split = pair.split("=", 2); // max 2 parts

Putting it all together:

String aString = "name==p==?header=hello?aname=?????lname=lastname";
for (String pair : aString.split("\\?(?!\\?)")) {
    String[] split = pair.split("=", 2);
    System.out.println(split[0] + " is " + split[1]);
}

Output:

name is =p==
header is hello
aname is ????
lname is lastname
Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

You can try like this

String[] vals = "Hello??Man?HowAreYou????".split("\\?+");
System.out.println(vals[0]+vals[1]+vals[2]);

OUTPUT

HelloManHowAreYou

But as aname=????? you want to get you can replace the ????? Five Question Marks with Other Symbol and replace back to ????? after split

String processed="Hello????Good? ? ....???".replace("????","*");

OUTPUT

Hello*Good? ? ....???

And than use split for ?

akash
  • 22,664
  • 11
  • 59
  • 87
  • your replace only works if there are 4 question marks in the input. What if there are more or less? – Absurd-Mind May 16 '14 at 13:52
  • @Absurd-Mind Yes agree!!! But before I start editing my answer I saw the answer is already there which is posted by `Bohemian`. – akash May 16 '14 at 14:38
0

Here the code, you are looking .

Implemented using the Split and HashMap.

Tested and Executed.

import java.util.HashMap;
import java.util.Map;


    public class Sample {

        public static void main(String[] args) {
            // TODO Auto-generated method stub


    //      String[] vals = "Hello??Man?HowAreYou????".split("\\?+");
    //      System.out.println(vals[0]+vals[1]+vals[2]);

            String query="name==p==?header=hello?aname=?????lname=lastname";
               String[] params = query.split("\\?");  
                Map<String, String> map = new HashMap<String, String>();  
                for (String param : params)  
                {  
                    String name = param.split("=")[0];  
                    String value = param.substring(name.length(),param.length());  
                    map.put(name, value);  
                    System.out.println(name);
                    if(name.equals("")){
                        value+="?";
                    }
                    System.out.println(value.replaceAll(" ", ""));
                }  

        }

    }
Sireesh Yarlagadda
  • 12,978
  • 3
  • 74
  • 76
0

I assume you are parsing URLs. The correct way would be to encode all special characters like ?, & and = which are values or names.

Better Solution: Encoding characters:

String name = "=p==";
String aname = "aname=????";
String lname = "lastname";
String url = "name=" + URLEncoder.encode(name, "UTF-8") +
             "?aname=" + URLEncoder.encode(aname, "UTF-8") +
             "?lname=" + URLEncoder.encode(lname, "UTF-8");

After that you have something like this:

name=&#61;p&#61;&#61;?aname=&#63;&#63;&#63;&#63;?lname=lastname

This can be splitted and decoded easily.

Other Solution: Bad input parsing:

If you insist, this works also. You can use a regex:

Pattern pattern = Pattern.compile("(\\w+?)=(\\S+?\\?+)");
Matcher m = pattern.matcher(query + "?");
while (m.find()) {
    String key = m.group(1);
    String value = m.group(2);
    value = value.substring(0, value.length() - 1);
    System.out.println(key + " = " +value);
}
Absurd-Mind
  • 7,884
  • 5
  • 35
  • 47