Is there any Java equivalent of PHP's http_build_query function? - java

I have a Map with my data and want to build a query string with it, just like I would with http_build_query on PHP. I'm not sure if this code is the best implementation of it or if I'm forgetting something?
public String toQueryString(Map<?, ?> data) throws UnsupportedEncodingException {
StringBuffer queryString = new StringBuffer();
for (Entry<?, ?> pair : data.entrySet()) {
queryString.append ( URLEncoder.encode ( (String) pair.getKey (), "UTF-8" ) + "=" );
queryString.append ( URLEncoder.encode ( (String) pair.getValue (), "UTF-8" ) + "&" );
}
if (queryString.length () > 0) {
queryString.deleteCharAt ( queryString.length () - 1 );
}
return queryString.toString ();
}

look at the QueryStringBuilder class and its test class :
private String httpBuildQuery(Map<String, String> data)
throws UnsupportedEncodingException {
QueryStringBuilder builder = new QueryStringBuilder();
for (Entry<String, String> pair : data.entrySet()) {
builder.addQueryParameter(pair.getKey(), pair.getValue());
}
return builder.encode("UTF-8");
}

The true power of PHP http_build_query function is its ability to get associative array and translate it into URL string. The following code do similar thing and it allows url params to be constructed as multi level Map that include nested Map and Collections.With some more work this a support for Array can also be added.
Test methods are shown below.
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
/**
* Class: URLBuilder
* User: Gilad Tiram
* Date: 6/12/13
* Time: 4:02 PM
* <p/>
* <p/>
* Utility that helps to build URL String
*/
public class URLBuilder {
/**
* Build URL string from Map of params. Nested Map and Collection is also supported
*
* #param params Map of params for constructing the URL Query String
* #param encoding encoding type. If not set the "UTF-8" is selected by default
* #return String of type key=value&...key=value
* #throws java.io.UnsupportedEncodingException
* if encoding isnot supported
*/
public static String httpBuildQuery(Map<String, Object> params, String encoding) {
if (isEmpty(encoding)) {
encoding = "UTF-8";
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
if (sb.length() > 0) {
sb.append('&');
}
String name = entry.getKey();
Object value = entry.getValue();
if (value instanceof Map) {
List<String> baseParam = new ArrayList<String>();
baseParam.add(name);
String str = buildUrlFromMap(baseParam, (Map) value, encoding);
sb.append(str);
} else if (value instanceof Collection) {
List<String> baseParam = new ArrayList<String>();
baseParam.add(name);
String str = buildUrlFromCollection(baseParam, (Collection) value, encoding);
sb.append(str);
} else {
sb.append(encodeParam(name));
sb.append("=");
sb.append(encodeParam(value));
}
}
return sb.toString();
}
private static String buildUrlFromMap(List<String> baseParam, Map<Object, Object> map, String encoding) {
StringBuilder sb = new StringBuilder();
String token;
//Build string of first level - related with params of provided Map
for (Map.Entry<Object, Object> entry : map.entrySet()) {
if (sb.length() > 0) {
sb.append('&');
}
String name = String.valueOf(entry.getKey());
Object value = entry.getValue();
if (value instanceof Map) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(name);
String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
sb.append(str);
} else if (value instanceof List) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(name);
String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
sb.append(str);
} else {
token = getBaseParamString(baseParam) + "[" + name + "]=" + encodeParam(value);
sb.append(token);
}
}
return sb.toString();
}
private static String buildUrlFromCollection(List<String> baseParam, Collection coll, String encoding) {
StringBuilder sb = new StringBuilder();
String token;
if (!(coll instanceof List)) {
coll = new ArrayList(coll);
}
List arrColl = (List) coll;
//Build string of first level - related with params of provided Map
for (int i = 0; i < arrColl.size(); i++) {
if (sb.length() > 0) {
sb.append('&');
}
Object value = (Object) arrColl.get(i);
if (value instanceof Map) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(String.valueOf(i));
String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
sb.append(str);
} else if (value instanceof List) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(String.valueOf(i));
String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
sb.append(str);
} else {
token = getBaseParamString(baseParam) + "[" + i + "]=" + encodeParam(value);
sb.append(token);
}
}
return sb.toString();
}
private static String getBaseParamString(List<String> baseParam) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < baseParam.size(); i++) {
String s = baseParam.get(i);
if (i == 0) {
sb.append(s);
} else {
sb.append("[" + s + "]");
}
}
return sb.toString();
}
/**
* Check if String is either empty or null
*
* #param str string to check
* #return true if string is empty. Else return false
*/
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
private static String encodeParam(Object param) {
try {
return URLEncoder.encode(String.valueOf(param), "UTF-8");
} catch (UnsupportedEncodingException e) {
return URLEncoder.encode(String.valueOf(param));
}
}
/* ========================================================================= */
/* Test functions */
/* ========================================================================= */
public static void main(String[] args) {
//basicTest();
//testWithMap();
//testWithList();
//testWithNestedMap();
//testWithNestedList();
testCompound();
}
private static void basicTest() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
params.put("c", "3");
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithMap() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
Map<String, Object> cParams = new LinkedHashMap<String, Object>();
cParams.put("c1", "c1val");
cParams.put("c2", "c2val");
params.put("c", cParams);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithNestedMap() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>();
cParamsLevel1.put("cL1-1", "cLevel1-1val");
cParamsLevel1.put("cL1-2", "cLevel1-2val");
Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>();
cParamsLevel2.put("cL2-1", "cLevel2-1val");
cParamsLevel2.put("cL2-2", "cLevel2-2val");
cParamsLevel1.put("cL1-3", cParamsLevel2);
params.put("c", cParamsLevel1);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithList() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
List<Object> cParams = new ArrayList<Object>();
cParams.add("c1val");
cParams.add("c2val");
params.put("c", cParams);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithNestedList() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
List<Object> cParamsLevel1 = new ArrayList<Object>();
cParamsLevel1.add("cL1-val1");
cParamsLevel1.add("cL12-val2");
List<Object> cParamsLevel2 = new ArrayList<Object>();
cParamsLevel2.add("cL2-val1");
cParamsLevel2.add("cL2-val2");
cParamsLevel1.add(cParamsLevel2);
params.put("c", cParamsLevel1);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testCompound() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
//flat
params.put("a", "1");
params.put("b", "2");
//Map level 1
Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>();
cParamsLevel1.put("cL1-1", "cLevel1-1val");
cParamsLevel1.put("cL1-2", "cLevel1-2val");
//Map level 2
Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>();
cParamsLevel2.put("cL2-1", "cLevel2-1val");
cParamsLevel2.put("cL2-2", "cLevel2-2val");
cParamsLevel1.put("cL1-3", cParamsLevel2);
params.put("c", cParamsLevel1);
//List level 1
List<Object> dParamsLevel1 = new ArrayList<Object>();
dParamsLevel1.add("dL1-val1");
dParamsLevel1.add("dL12-val2");
//List level 2
List<Object> dParamsLevel2 = new ArrayList<Object>();
dParamsLevel2.add("dL2-val1");
dParamsLevel2.add("dL2-val2");
dParamsLevel1.add(dParamsLevel2);
params.put("d", dParamsLevel1);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
}
For easy test of your results append the string resulted by tests as query String of real url that point to this PHP. Example
http://localhost/test.php?a=1&b=2&c[cL1-1]=cLevel1-1val&c[cL1-2]=cLevel1-2val&c[cL1-3][cL2-1]=cLevel2-1val&c[cL1-3][cL2-2]=cLevel2-2val&d[0]=dL1-val1&d[1]=dL12-val2&d[2][0]=dL2-val1&d[2][1]=dL2-val2
<?php
var_dump($_REQUEST);
?>

You'd probably want to check the "Accept" request header for the encodings supported by the client before forcing UTF-8 (even though it's probably the best choice).

This should be the easiest (and most reliable) solution:
protected static String httpBuildQuery(List<? extends NameValuePair> parameters, String encoding) {
return URLEncodedUtils.format(parameters, encoding).replace("*", "%2A");
}
Example usage:
List<NameValuePair> params = new ArrayList<NameValuePair>;
params.add(new BasicNameValuePair("key", "value"));
String queryString = httpBuildQuery(myParamList, "UTF-8");
Java not encoding the asterisk (+) while PHP does encode it %2A should be the only difference.

Looks OK, with these caveats:
make the parameter a Map<String, String> rather than casting key and value to String.
the hardcoded encoding looks suspicious. UTF-8 is not a given, it has to match the encoding defined in the header of the HTTP request. So the code should ensure that they do - at least define it as a constant somewhere and refer to that both here and wherever the request encoding is set.
Edit: It seems that I was wrong about the encoding; HTTP GET parameters are not subject to an encoding header, and did not traditionally have a well-defined encoding at all. RFC 3988 does seem to mandate UTF-8, but that sounds rather brittle to me, so unless you have tight control over the server and can ensure that it does indeed use UTF-8 as well, I'd use POST requests for any data that's not in the 7bit ASCII range.

Related

JUnit Comparing XML to Text

I'm trying to compare my Input XML to an expected TXT
But somehow it fails and I have no clue why. I think this is because I'm writing a negative test (expected TXT contains error message, which is produced by xquery due to invalid inputs)
Comparing two XMLs are working(without negative test).
public void testHeader(String inputHeaderFileName, String expectedResultFileName) throws Exception {
HashMap<String, Object> xqueryParametersMap = new HashMap<String, Object>();
xqueryParametersMap.put("udgHeader", db.parse(getFileFromTestDataBasePath(inputHeaderFileName)));
this.test(xqueryParametersMap, expectedResultFileName);
}
public void test(Map<String, Object> xqueryParametersMap, String expectedResultFileName) throws Exception {
String expectedOutput = readFile(testDataBasePath + File.separator + expectedResultFileName, encoding);
String result = transform(xqueryParametersMap).xmlText(new XmlOptions().setSavePrettyPrint().setSavePrettyPrintIndent(2));
if (printTransformedXmlToConsoleBoolean) System.out.println(result);
Diff diff = new Diff(expectedOutput, result);
diff.overrideDifferenceListener(new IgnoreTextAndAttributeValuesDifferenceListener());
assertTrue("Grundstruktur des Resultats ist anders als in '" + expectedResultFileName + "' erwartet!\n\n" + diff + "\n\n", diff.similar());
DetailedDiff detailDiff = new DetailedDiff(compareXML(expectedOutput, result));
#SuppressWarnings("unchecked")
List<Difference> allDifferences = detailDiff.getAllDifferences();
assertEquals("Tatsaechliches Ergebnis weicht von '" + expectedResultFileName + "' ab!\n\n" + detailDiff + "\n\n", 0, allDifferences.size());
}
private XmlObject transform(Map<String, Object> xqueryParametersMap) throws Exception {
XmlObject xmlObject = XmlObject.Factory.newInstance();
XmlOptions options = new XmlOptions();
Map<String, Object> paramMap = new HashMap<String, Object>();
Iterator<Entry<String, Object>> it = xqueryParametersMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Object> pairs = it.next();
Object value = pairs.getValue();
String key = pairs.getKey();
if (value instanceof Document) {
XmlObject inputXml = XmlObject.Factory.parse(getStringFromDocument((Document) value));
paramMap.put(key, getXmlObject(inputXml));
} else if (value instanceof String) {
XmlString string = XmlString.Factory.newInstance();
string.setStringValue(value.toString());
paramMap.put(key, string);
}
}
String xqueryFileContent = readFile(xQueryUnderTestPath, encoding);
options.setXqueryVariables(paramMap);
xqueryFileContent = xqueryFileContent.replaceAll("(?s)\\s*?\\(:.*?:\\)", "");
XmlObject[] resultsObjects = xmlObject.execQuery(xqueryFileContent, options);
if (resultsObjects.length < 1)
{
//throw new NoResultException();
throw new Exception("Xquery transformation did not return a result");
}
else if (resultsObjects.length > 1)
{
//throw new NonUniqueResultException("result size is '" + resultsObjects.length + "'");
throw new Exception("Xquery transformation did return more than one result: " + resultsObjects.length);
}
else return resultsObjects[0];
}
'
The test:
public void testRecipientListNegative() throws Exception {
recipientTester.testHeader("input.xml", "expected.txt");
}
Stacktrace:
org.apache.xmlbeans.XmlRuntimeException: weblogic.xml.query.exceptions.XQueryUserException: line 29, column 5: fase: Unknown msg-name/recipient combination ['ARS_XYZ'/'ESM']! Please check fase recipient list.
at weblogic.xml.query.runtime.core.Error.fetchNext(Error.java:61)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.runtime.core.IfThenElse.fetchNext(IfThenElse.java:91)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.runtime.core.IfThenElse.fetchNext(IfThenElse.java:91)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.runtime.constructor.AtomicElementConstructor.fetchNext(AtomicElementConstructor.java:129)
at weblogic.xml.query.iterators.GenericIterator.peekNext(GenericIterator.java:163)
at weblogic.xml.query.runtime.constructor.SuperElementConstructor.getPhase2(SuperElementConstructor.java:388)
at weblogic.xml.query.runtime.constructor.PartMatElemConstructor.matEverything(PartMatElemConstructor.java:123)
at weblogic.xml.query.runtime.constructor.PartMatElemConstructor.fetchNext(PartMatElemConstructor.java:197)
at weblogic.xml.query.iterators.GenericIterator.peekNext(GenericIterator.java:163)
at weblogic.xml.query.runtime.constructor.SuperElementConstructor.getPhase2(SuperElementConstructor.java:388)
at weblogic.xml.query.runtime.constructor.PartMatElemConstructor.fetchNext(PartMatElemConstructor.java:229)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.runtime.core.LetIterator.fetchNext(LetIterator.java:133)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.runtime.core.LetIterator.fetchNext(LetIterator.java:133)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.xdbc.iterators.ItemIterator.fetchNext(ItemIterator.java:86)
at weblogic.xml.query.iterators.LegacyGenericIterator.next(LegacyGenericIterator.java:109)
at weblogic.xml.query.runtime.qname.InsertNamespaces.fetchNext(InsertNamespaces.java:216)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at weblogic.xml.query.runtime.core.ExecutionWrapper.fetchNext(ExecutionWrapper.java:88)
at weblogic.xml.query.iterators.GenericIterator.next(GenericIterator.java:104)
at org.apache.xmlbeans.impl.store.XqrlImpl$SegmentedIterator.next(XqrlImpl.java:1656)
at org.apache.xmlbeans.impl.store.XqrlImpl.loadTokenStream(XqrlImpl.java:1410)
at org.apache.xmlbeans.impl.store.XqrlImpl.loadTokenStream(XqrlImpl.java:1383)
at org.apache.xmlbeans.impl.store.XqrlImpl.executeQueryToXmlObjects(XqrlImpl.java:1575)
at org.apache.xmlbeans.impl.store.XqrlImpl.access$000(XqrlImpl.java:53)
at org.apache.xmlbeans.impl.store.XqrlImpl$CompiledQuery.objectExecute(XqrlImpl.java:302)
at org.apache.xmlbeans.impl.store.Query.objectExecQuery(Query.java:80)
at org.apache.xmlbeans.impl.store.Xobj.exec_query(Xobj.java:2525)
at org.apache.xmlbeans.impl.values.XmlObjectBase.execQuery(XmlObjectBase.java:525)
at de.db.udg.componenttest.XQueryTester.transform(XQueryTester.java:271)
at de.db.udg.componenttest.XQueryTester.test(XQueryTester.java:210)
at de.db.udg.componenttest.XQueryTester.testHeader(XQueryTester.java:172)
at XQueryTest.testRecipientListNegative(XQueryTest.java:38)
the lines which are failing according to stacktrace:
this.test(xqueryParametersMap, expectedResultFileName);
String result = transform(xqueryParametersMap).xmlText(new XmlOptions().setSavePrettyPrint().setSavePrettyPrintIndent(2));
XmlObject[] resultsObjects = xmlObject.execQuery(xqueryFileContent, options);

Parse String to get grouped parameters

My String looks like this
http://localhost:8080/HospitalServer/files/file?id=34&firstname=alex&lastname=ozouf&age=33&firstname=kevin&lastname=gerfild&age=27
I use this code to parse the parameters
final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
final String[] pairs = query.split("&");
for (String pair : pairs) {
final int idx = pair.indexOf("=");
final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
if (!query_pairs.containsKey(key)) {
query_pairs.put(key, new LinkedList<String>());
}
final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
query_pairs.get(key).add(value);
}
System.out.println(query_pairs);
The result is
{id=[34], firstname=[alex, kevin], lastname=[ozouf, gerfild], age=[33, 27]}
The result is not too bad but I want to group the parameters by person.
{id=[34], 1=[alex,ozouf,33 ], 2=[kevin, gerfild,27]}
I can create it from the previous result but I have the feeling that the job is done twice. What do you think I shall do ?
Here's how you can do it without using any library:
import java.util.Map;
import java.util.HashMap;
public class MyUrlParser {
private static final String SEPARATOR = ",";
public static void main(String[] args) {
final String URL = "http://localhost:8080/HospitalServer/files/file?id=34&firstname=alex&lastname=ozouf&age=33&firstname=kevin&lastname=gerfild&age=27";
MyUrlParser mup = new MyUrlParser();
try {
Map<String, String> parsed = mup.parse(URL);
System.out.println(parsed);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
public Map<String, String> parse(String url) throws Exception {
Map<String, String> retMap = new HashMap<>();
int queryStringPos = url.indexOf("?");
if (-1 == queryStringPos) {
throw new Exception("Invalid URL");
}
String queryString = url.substring(queryStringPos + 1);
String[] parameters = queryString.split("&");
if (parameters.length > 0) {
retMap.put("id", parameters[0]);
int personCounter = 0;
for (int minSize = 4; minSize <= parameters.length; minSize += 3) {
StringBuilder person = new StringBuilder();
person.append(parameters[minSize-3]);
person.append(SEPARATOR);
person.append(parameters[minSize-2]);
person.append(SEPARATOR);
person.append(parameters[minSize-1]);
personCounter++;
retMap.put("person" + personCounter, person.toString());
}
}
return retMap;
}
}

Get first two lines from a file put it into hasmap as key and whole file as value of hashmap.And write hashmap to a file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Now consider two input files
1.post_tran.tbl(edited table)
[name]post_tran_id[/name]=[data] 1[/data]
[name]tran_nr[/name]=[data]2[/data]
[name]datetime_tran_local[/name]=[data]2002-04-02 19:02:28[/data]
[name]system_trace_audit_nr[/name]=[data]008497[/data]
[name]settle_amount_rsp[/name]=[data]4120[/data]
[name]settle_tran_fee_rsp[/name]=[data]10[/data]
[name]post_tran_cust_id[/name]=[data] 2[/data]
[name]prev_post_tran_id[/name]=[data] 0[/data]
[name]next_post_tran_id[/name]=[data]0[/data]
[name]message_type[/name]=[data]0200[/data]
[name]post_tran_id[/name]=[data] 2[/data]
[name]tran_nr[/name]=[data]2[/data]
[name]datetime_tran_local[/name]=[data]2002-04-02 19:02:28[/data]
[name]system_trace_audit_nr[/name]=[data]008497[/data]
[name]settle_amount_rsp[/name]=[data]4120[/data]
[name]settle_tran_fee_rsp[/name]=[data]10[/data]
[name]post_tran_cust_id[/name]=[data] 2[/data]
[name]prev_post_tran_id[/name]=[data] 0[/data]
[name]next_post_tran_id[/name]=[data]0[/data]
[name]message_type[/name]=[data]0200[/data]
2.post_tran_cust.tbl
[name]post_tran_cust_id[/name]=[data]1[/data]
[name]source_node_name[/name]=[data]TestSrc[/data]
[name]draft_capture[/name]=[data]0[/data]
[name]pan[/name]=[data]5892790010003952[/data]
[name]card_seq_nr[/name]=[data]NULL[/data]
[name]expiry_date[/name]=[data]0415[/data]
[name]post_tran_cust_id[/name]=[data]2[/data]
[name]source_node_name[/name]=[data]SrcDec[/data]
[name]draft_capture[/name]=[data]1[/data]
[name]pan[/name]=[data]5892790010003952[/data]
[name]card_seq_nr[/name]=[data]890[/data]
[name]expiry_date[/name]=[data]0816[/data]
These are the sample files which i need to process.below is the sample code.The code contains 2 hashmaps.
One hashmap is for post_tran.tbl which contains data values of first 2 rows as keys for hashmap and value is the corresponding whole record with first two rows. Second hashmap is for post_tran_cust which contains data value of first row as key for hashmap and value is corresponding whole record with first row.
Now I want to compare keys(for first hashmap i need only post_tran_cust_id)
on both hashmaps i.e post_tran_cust_id from hashmap1 and post_tran_cust_id
from hasmp2. If there exists a match then the corresponding records from
both hashmaps are to be written into file.Kindly help me out.
Here is my code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
public class Migrator {
void migrate(String post_tran, String post_tran_cust) throws IOException {
Map<String, Map<String, String>> h1 = loadFile(post_tran, KEY1);
Map<String, Map<String, String>> h2 = loadFile(post_tran_cust,
KEY2);
// System.out.println("Hash Post_Tran................\n: " + h1);
// System.out.println("Hash Post_Tran_Cust................\n: " +
h2);
PrintStream out = new
PrintStream("D:\\Postcard_workspace_new\\Final\\final.tbl");
// PrintStream out = System.out; // Used during testing
for (Map.Entry<String, Map<String, String>> entry : h1.entrySet()) {
Map<String, String> data = entry.getValue();
if (h2.containsKey(data.get(KEY2))) {
print(out, KEY1, data.get(KEY1));
print(out, KEY2, data.get(KEY2));
// Print remaining rows in any order
for (String key : data.keySet()) {
if ( ! key.equals(KEY1) && ! key.equals(KEY2) ) {
print(out, key, data.get(key));
}
}
data = h2.get(data.get(KEY2));
for (String key : data.keySet()) {
if ( ! key.equals(KEY2) ) {
print(out, key, data.get(key));
}
}
out.println(); // Record separator
}
}
}
private Map<String, Map<String, String>> loadFile(String fileName, String
key) throws IOException {
Map<String, Map<String, String>> result = new HashMap<String,
Map<String, String>>();
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
do {
Map<String, String> data = new HashMap<String, String>();
while ((line = br.readLine()) != null && !line.isEmpty()) {
data.put(getKey(line), getData(line));
}
result.put(data.get(key), data);
} while (line != null);
br.close();
return result;
}
public static void main(String[] args) throws IOException {
Migrator mg = new Migrator();
mg.migrate("post_tran.tbl","post_tran_cust.tbl");
}
}
The following assumes that empty lines are really empty, i.e. no spaces and such, and that there are no empty lines in the beginning.
Since I now understand a little bit more what it is you're trying to do, I have re-made a lot of the logic in this update.
No specific error handling to make it simpler.
public class Migrator {
private static final String KEY1 = "post_tran_id";
private static final String KEY2 = "post_tran_cust_id";
void migrate(String post_tran, String post_tran_cust) throws IOException {
Map<String, Map<String, String>> h1 = loadFile(post_tran, KEY1);
Map<String, Map<String, String>> h2 = loadFile(post_tran_cust, KEY2);
PrintStream out = new PrintStream("final.tbl");
for (Map.Entry<String, Map<String, String>> entry : h1.entrySet()) {
Map<String, String> data = entry.getValue();
String k = data.get(KEY2);
if (k != null && h2.containsKey(k.trim())) {
print(out, KEY1, data.get(KEY1));
print(out, KEY2, data.get(KEY2));
// Print remaining rows in any order
for (String key : data.keySet()) {
if ( ! key.equals(KEY1) && ! key.equals(KEY2) ) {
print(out, key, data.get(key));
}
}
data = h2.get(k.trim());
for (String key : data.keySet()) {
if ( ! key.equals(KEY2) ) {
print(out, key, data.get(key));
}
}
out.println(); // Record separator
}
}
}
private void print(PrintStream out, String key, String data) {
out.print("[name]");
out.print(key);
out.print("[/name]");
out.print("=");
out.print("[data]");
out.print(data);
out.print("[/data]");
out.println();
}
private Map<String, Map<String, String>> loadFile(String fileName, String key) throws IOException {
Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
do {
Map<String, String> data = new HashMap<String, String>();
while ((line = br.readLine()) != null && !line.isEmpty()) {
data.put(getKey(line), getData(line));
}
result.put(data.get(key).trim(), data);
} while (line != null);
br.close();
return result;
}
private String getKey(String line) {
String[] tokens = line.split("=");
int length = tokens[0].length();
return tokens[0].substring(6, length - 7);
}
private String getData(String line) {
String[] tokens = line.split("=");
int length = tokens[1].length();
return tokens[1].substring(6, length - 7);
}
public static void main(String[] args) throws IOException {
Migrator mg = new Migrator();
mg.migrate("post_tran.tbl", "post_tran_cust.tbl");
}
}

extract image name from URL java

http://m.people.com/img/ic?width=474&height=269&fsize=999000&format=jpg&url=http%3A%2F%2Fimg2.timeinc.net%2Fpeople%2Fi%2F2011%2Fnews%2F110425%2Fgwyneth-paltrow-300.jpg
This is my url.How can I extract image name Fgwyneth-paltrow-300.jpg from the URL in java.
Thanks
First we want to decode the URL and get the url parameter. We can do that using BalusC's great code for parsing query Strings. Then we just have to split that URL by / and take the last part.
String url ="http://m.people.com/img/ic?width=474&height=269&fsize=999000&format=jpg&url=http%3A%2F%2Fimg2.timeinc.net%2Fpeople%2Fi%2F2011%2Fnews%2F110425%2Fgwyneth-paltrow-300.jpg";
Map<String, List<String>> params = new HashMap<String, List<String>>();
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key;
try
{
key = URLDecoder.decode(pair[0], "UTF-8");
} catch (UnsupportedEncodingException e)
{
key = URLDecoder.decode(pair[0]);
}
String value;
try
{
value = URLDecoder.decode(pair[1], "UTF-8");
} catch (UnsupportedEncodingException e)
{
value = URLDecoder.decode(pair[1]);
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
}
String img = params.get("url").get(0);
String[] parts = img.split("/");
String imgName = parts[parts.length - 1];
System.out.println(imgName);

How to extract parameters from a given url

In Java I have:
String params = "depCity=PAR&roomType=D&depCity=NYC";
I want to get values of depCity parameters (PAR,NYC).
So I created regex:
String regex = "depCity=([^&]+)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(params);
m.find() is returning false. m.groups() is returning IllegalArgumentException.
What am I doing wrong?
It doesn't have to be regex. Since I think there's no standard method to handle this thing, I'm using something that I copied from somewhere (and perhaps modified a bit):
public static Map<String, List<String>> getQueryParams(String url) {
try {
Map<String, List<String>> params = new HashMap<String, List<String>>();
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
}
return params;
} catch (UnsupportedEncodingException ex) {
throw new AssertionError(ex);
}
}
So, when you call it, you will get all parameters and their values. The method handles multi-valued params, hence the List<String> rather than String, and in your case you'll need to get the first list element.
Not sure how you used find and group, but this works fine:
String params = "depCity=PAR&roomType=D&depCity=NYC";
try {
Pattern p = Pattern.compile("depCity=([^&]+)");
Matcher m = p.matcher(params);
while (m.find()) {
System.out.println(m.group());
}
} catch (PatternSyntaxException ex) {
// error handling
}
However, If you only want the values, not the key depCity= then you can either use m.group(1) or use a regex with lookarounds:
Pattern p = Pattern.compile("(?<=depCity=).*?(?=&|$)");
It works in the same Java code as above. It tries to find a start position right after depCity=. Then matches anything but as little as possible until it reaches a point facing & or end of input.
I have three solutions, the third one is an improved version of Bozho's.
First, if you don't want to write stuff yourself and simply use a lib, then use Apache's httpcomponents lib's URIBuilder class: http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html
new URIBuilder("http://...").getQueryParams()...
Second:
// overwrites duplicates
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
public static Map<String, String> readParamsIntoMap(String url, String charset) throws URISyntaxException {
Map<String, String> params = new HashMap<>();
List<NameValuePair> result = URLEncodedUtils.parse(new URI(url), charset);
for (NameValuePair nvp : result) {
params.put(nvp.getName(), nvp.getValue());
}
return params;
}
Third:
public static Map<String, List<String>> getQueryParams(String url) throws UnsupportedEncodingException {
Map<String, List<String>> params = new HashMap<String, List<String>>();
String[] urlParts = url.split("\\?");
if (urlParts.length < 2) {
return params;
}
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
}
// skip ?& and &&
if ("".equals(key) && pair.length == 1) {
continue;
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
return params;
}
If you are developing an Android application, try this:
String yourParam = null;
Uri uri = Uri.parse(url);
try {
yourParam = URLDecoder.decode(uri.getQueryParameter(PARAM_NAME), "UTF-8");
} catch (UnsupportedEncodingException exception) {
exception.printStackTrace();
}
If spring-web is present on classpath, UriComponentsBuilder can be used.
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUriString(url).build().getQueryParams();
Simple Solution create the map out of all param name and values and use it :).
import org.apache.commons.lang3.StringUtils;
public String splitURL(String url, String parameter){
HashMap<String, String> urlMap=new HashMap<String, String>();
String queryString=StringUtils.substringAfter(url,"?");
for(String param : queryString.split("&")){
urlMap.put(StringUtils.substringBefore(param, "="),StringUtils.substringAfter(param, "="));
}
return urlMap.get(parameter);
}
same but with jsonobject:
public static JSONObject getQueryParams2(String url) {
JSONObject json = new JSONObject();
try {
String[] urlParts = url.split("\\?");
JSONArray array = new JSONArray();
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
if(json.has(key)) {
array = json.getJSONArray(key);
array.put(value);
json.put(key, array);
array = new JSONArray();
} else {
array.put(value);
json.put(key, array);
array = new JSONArray();
}
}
}
}
return json;
} catch (Exception ex) {
throw new AssertionError(ex);
}
}

Categories