I am implementing a chat system and I am running into a problem while parsing the message.
As part of the message string, I have sending a bunch of key params like this
key1:value1,key2:value2,key3:value3,message:"random text with character : /" etc.
I will later parse this string using split on command and colon. However one of the params is message which can contain both command and colon. so if the message has any of those characters, it will break my parse logic. So is there any way I can escape these characters in the message string? I tried adding two backslashes to escape it but that did not work.
parse code
String[] params = chat.split(",");
for(String param:params){
String[]pair = param.split(":");
if(pair.length != 2){
String key = pair[0];
String value = pair[1];
}else{
return null;
}
}
you question isn't clear i need more example and the best way to receive the messages in JSON format thats makes your job much more cleab but i provide two answers .
For just getting the message as raw( if you are sure that the key value will be "message" and capture everything in the second part):
for(String param:params){
if (param.contains("message")){
String[] pairs=param.split("message:");
String key = "message";
String value = pairs[1];
}
String[]pair = param.split(":");
if(pair.length != 2){
String key = pair[0];
String value = pair[1];
}else{
return null;
}
}
return:
"random text with character : /" etc.
For escaping the special character in string you have to use the following method :
for(String param:params){
if (param.contains("message")){
String[] pairs=param.split("message:");
String key = "message";
String value = StringEscapeUtils.escapeJava(pairs[1]);
}
String[]pair = param.split(":");
if(pair.length != 2){
String key = pair[0];
String value = pair[1];
}else{
return null;
}
return:
\"random text with character : /\" etc.
you have to import Apache Commons Lang ยป 3.0 here is the link for maven :
http://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.0
Related
I'm a writing a parser that will extract the tag and value out of a line that it reads from a file and I want to know how to get the value. So in this case I want to get
key = "accountName" and
value = "fname LName" and have it repeat with each line.
<accountName>fname LName</accountName>
<accountNumber>12345678912</accountNumber>
<accountOpenedDate>20200218</accountOpenedDate>
This is my code, this is within a while loop that is scanning each line using bufferedReader. I managed to get the key properly, but when I try to get the value, I get "String index out of range - 12. Not sure how to get the value between the two arrows > <.
String line;
if(line.startsWith("<"){
key = line.substring(line.indexOf("<"+1, line.indexOf(">"));
value = line.substring(line.indexOf(">"+1, line.indexOf("<")+1);
}
Though it is recommended to use XML parser but still if you want to do it by manually processing the string at each line:
(using regular expression is recommended to process line) but if you want todo manually with substring way here is the example:
private static void readKeyValue(String line) {
String key = null;
String value = null;
if (null != line && line.startsWith("<") && line.contains("</")) {
key = line.substring(line.indexOf("</")+ 2 , line.lastIndexOf(">"));
value = line.substring(line.indexOf(">") + 1, line.indexOf("</"));
}
System.out.println("key: "+ key);
System.out.println("value: "+ value);
}
You can use regular expressions to extract, assuming the line variable is a string read from each line.
String pattern = "<([a-zA-Z]+.*?)>([\\s\\S]*?)</[a-zA-Z]*?>";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
// find
if (m.find()) {
String key = m.group(1);
String value = m.group(2);
System.out.println("Key: " + key);
System.out.println("Value: " + value);
} else {
System.out.println("Invalid");
}
I'm currently trying to catch special chars from an URL to change them to their hex value (for example : "This shop" should transform into "This%20shop").
I was wondering if there was some clean was of looking into the string to find each special chars and replace them to their ascii values.
I try to do it because I have to pass PHP arguments into the url using GET.
Here would be an example of an url :
www.mysite.com/page?adress=I am Living here!
My code actually reaplace '%' and ' ' from URLs, but I'd like to change any special chars I've defined.
This is what I've done so far :
private final String specialChars = "!#\\[]`#$%&'()*+-<>=?";
public URL getURL(){
String tempUrl = baseURL;
Set<String> keys = this.arguments.keySet();
for (Map.Entry<String, String> entry : arguments.entrySet()) {
String value = entry.getValue();
if(entry.getValue().contains(specialChars)){
Log.e("INFO", "THIS URL CONTAINS SPECIAL CHARS");
}
//Replacing % char
if(entry.getValue().contains("%")){
Log.i("URL BUILD INFO", "URL ARGS CONTAINS '%'");
value = entry.getValue().replace("%", "%25");
}
//Replacing spaces
if(entry.getValue().contains(" ")){
Log.i("URL BUILD INFO", "URL ARGS CONTAINS SPACE");
value = entry.getValue().replace(" ", "%20");
}
baseURL += entry.getKey() + "=" + value + "&";
}
try{
this.url = new URL(baseURL);
} catch(MalformedURLException e){
Log.e("URL MALFORMED", "YOUR IS MALFORMED");
e.printStackTrace();
}
Log.d("URL IS VALID", url.toString());
return url;
}
From what I understood from String documentation, matches method should only return true if my URL matches exactly my specialChars charSequence, which isn't what I want. But I can't find any other method to do what I'm trying to achieve on the String documentation.
If you're just trying to handle url encoding there are existing solutions for that - see URLEncoder and URLDecoder (good previous answer here)
I am having the below string in a string variable in java.
rule "6"
no-loop true
when
then
String prefix = null;
prefix = "900";
String style = null;
style = "490";
String grade = null;
grade = "GL";
double basePrice = 0.0;
basePrice = 837.00;
String ruleName = null;
ruleName = "SIVM_BASE_PRICE_006
Rahul Kumar Singh";
ProductConfigurationCreator.createFact(drools, prefix, style,grade,baseprice,rulename);
end
rule "5"
no-loop true
when
then
String prefix = null;
prefix = "800";
String style = null;
style = "481";
String grade = null;
grade = "FL";
double basePrice = 0.0;
basePrice = 882.00;
String ruleName = null;
ruleName = "SIVM_BASE_PRICE_005";
ProductConfigurationCreator.createFact(drools, prefix, style,grade,baseprice,rulename);
end
I need to replace this the carriage return between "THEN" and "END" keyword with white space so that it becomes like below code:
rule "6"
no-loop true
when
then
String prefix = null;
prefix = "900";
String style = null;
style = "490";
String grade = null;
grade = "GL";
double basePrice = 0.0;
basePrice = 837.00;
String ruleName = null;
ruleName = "SIVM_BASE_PRICE_006 Rahul Kumar Singh";
ProductConfigurationCreator.createFact(drools, prefix, style,grade,baseprice,rulename);
end
rule "5"
no-loop true
when
then
String prefix = null;
prefix = "800";
String style = null;
style = "481";
String grade = null;
grade = "FL";
double basePrice = 0.0;
basePrice = 882.00;
String ruleName = null;
ruleName = "SIVM_BASE_PRICE_005";
ProductConfigurationCreator.createFact(drools, prefix, style,grade,baseprice,rulename);
end
In the above two example of string set, the second is correct format that I need. However, in the first set, I am getting this :
ruleName = "SIVM_BASE_PRICE_006
Rahul Kumar Singh";
This perticulerly needs to be like this:
ruleName = "SIVM_BASE_PRICE_006 Rahul Kumar Singh";
and I also need to ensure that this doesn't effect any thing else in the string.
Thus I need to replace this "carriage return" with a white space and make in one line. This is my requirment. I tried with replace and replaceAll method of string but not works properly.
Problem:
I need to look in between string "then" and "end" and in that whenever
there is any carriage return in between two double quaotes "" ""; I
need to replace this carriage return with white space and make it in
one line.
Thanks
EDIT:
DRT:
template header
Prefix
Style
Product
package com.xx
import com.xx.drools.ProductConfigurationCreator;
template "ProductSetUp"
rule "Product_#{row.rowNumber}"
no-loop true
when
then
String prefix = null;
prefix = "#{Prefix}";
String style = null;
prefix = "#{Style}";
String product = null;
product = "#{Product}";
ProductConfigurationCreator.createProductFact(drools,prefix,style,product);
end
end template
The excel and drt are for only demostration purpose.
In the Image, in Product column, there is "SOFAS \rkumar shorav". Actually this is creating problem. This will generate like below:
product = "SOFAS
kumar shorav";
I need this like below:
product = "SOFAS kumar shorav";
Then Excel data :
attached image.
Instead of regex I would probably write my own formatter which will
check if cursor is inside quote
replace each \r with space
replace each \n with space, unless it was placed right after \r which means that space was already placed for that \r
write rest of characters without change.
Only possible problem is that this formatter will not care about where string is placed so if you want to format some specific part of the string you will need to provide only that part.
Code implementing such formatter can look like:
public static String format(String text){
StringBuilder sb = new StringBuilder();
boolean insideQuote = false;
char previous = '\0';//to track `\r\n`
for (char ch : text.toCharArray()) {
if (insideQuote &&
(ch == '\r' ||
ch == '\n' && previous != '\r') ) {
sb.append(" ");//replace `\r` or `\n` with space
}else {
if (ch == '"') {
insideQuote = !insideQuote;
}
sb.append(ch); //write other characters without change
}
previous = ch;
}
return sb.toString();
}
helper utility method
public static String format(File file, String encoding) throws IOException {
String text = new String(Files.readAllBytes(file.toPath()), encoding);
return format(text);
}
Usage:
String formatted = format(new File("input.txt"), "utf-8");
System.out.println(formatted);
You might say that there is a bug in org.drools.template.parser.StringCell, method
public void addValue(Map<String, Object> vars) {
vars.put(column.getName(), value);
}
Here, the value is added to the Map as a String but this does not take into account that string values are usually expanded into string literals. Therefore, an embedded newline should be converted to the escape sequence \n. You might try this patch:
public void addValue(Map<String, Object> vars) {
String h = value.replaceAll( "\n", "\\\\n" );
vars.put(column.getName(), h);
}
Take the source file, put it into a suitable subdirectory, compile it to a class file and make sure that the root directory precedes drools-templates-6.2.0.Final-sources.jar in the class path. You should then see
ruleName = "SIVM_BASE_PRICE_006\nRahul Kumar Singh";
in the generated DRL file. Obviously, this is not a space, but it is what is written in the spreadsheet cell!
I suggest (urgently) that you do not follow this approach. The reason is simply this that strings are not always expanded between quotes, and then the replacement would result almost certainly in invalid code. There is simply no remedy as the template compiler is "dumb" and does not really "know" what it is expanding.
If a String in a spreadsheet contains a line break, template expansion must render this faithfully, and break the line just there. If this produces invalid (Java) code: why was the line break entered in the first place? There is absolutely no reason not to have a space in that cell if that's what you want.
s = s.replaceAll("(?m)^([^\"]*(\"[^\"]*\")*[^\"]*\"[^\"]*)\r?\n\\s*", "$1 ");
This replaces lines with an unpaired quotes to one with the line ending replaced.
^.... means starting at the line begin
[^\"] means not quote
\r?\n catches both CR+LF (Windows) as LF (Rest) line endings
not-quotes,
repetition of " not-quotes ",
not quotes, quote, not-quotes, newline
Mind this does not cover backslash+quote, escapes them-selves.
Use the "multi line" flag:
str = str.replaceAll("(?m)^\\s+", "");
The multi-line flag (?m) makes ^ and $ match start/end of each line (rather than start/end of input). \s+ means "one or more whitespace characters".
I want to retrieve the info of a line of text from a textfile in 2 different strings...
This is the situation, getting the password line from pwd.txt :
String pwdRetrieved = retreivePwd.getPwd("pwd.txt");
However the password is crypted and it needs 2 valors, the password itself + a "key", like this:
4B5CB9348D5ADB733D43C2FB57A6A971-admin_pwd
admin_pwd is the "key" or "reference" to the encrypted password.
Now what I want to do is get 4B5CB9348D5ADB733D43C2FB57A6A971 into a string and admin_pwd into another string, is that possible?
More specific, i want to read from the .txt until the character "-" is found and store it into a String, then i want it to keep reading after "-" and store it into another string.
Read the whole string, split on the "-" and retrieve the two parts from the created array:
String pwdRetrieved = retreivePwd.getPwd("pwd.txt");
String[] splitPwdRetrieved = pwdRetrieved.split("-");
String password = splitPwdRetrieved[0];
String key = splitPwdRetrieved[1];
You can try this..
String[] pwd = pwdRetrieved.split("-");
After you can split this array value into individual strings.
Using String's split method will do the trick:
String[] split = pwdRetrieved.split("-");
Will return a string array with the two strings you are after
String[] split = pwdRetrieved.split("-");
String enc=split[0];
String pass=split[1];
you could split your String at the - after reading the whole line like this:
String pwdRetrieved = retreivePwd.getPwd("pwd.txt");
String[] split = pwdRetrieved .split("-");
System.out.println(split[0]);
System.out.println(split[1]);
You could do this:
String[] parts = pwdRetrieved.split("-");
String password = parts[0];
String key = parts[1];
Or do this:
int dashPosition = pwdRetrieved.indexOf("-");
String password = pwdRetrieved.substring(0, dashPosition);
String key = pwdRetrieved.substring(dashPosition + 1);
I want to parse the data below in java. What approach shall I follow?
I want to neglect ; inside { }.
Thus Version, Content, Provide, UserConfig and Icon as name and corresponding values.
Version:"1";
Content:2013091801;
Provide:"Airtel";
UserConfig :
{
Checksum = "sha1-234448e7e573b6dedd65f50a2da72245fd3b";
Source = "content\\user.ini";
};
Icon:
{
Checksum = "sha1-a99f835tytytyt3177674489770e613c89390a8c4";
Source = "content\\resept_ico.bmp";
};
Here we can't use String.split(";") function.
It would have been lot more complex to convert using the Regex and then creating a method to extract the required fields,
What I did was converted the above mentioned input to Json compatible string and then used GSON library by google to parse the String to my customized class,
class MyVer
{
String Version;
long Content;
String Provide;
Config UserConfig;
Config Icon;
String Source;
}
class Config
{
String Checksum;
String Source;
}
public static void main(String[] args)
{
String s = "Version:\"1\";Content:2013091801;Provide:\"Airtel\";UserConfig :{ Checksum = \"sha1-234448e7e573b6dedd65f50a2da72245fd3b\"; Source = \"content\\user.ini\";};Icon:{ Checksum = \"sha1-a99f835tytytyt3177674489770e613c89390a8c4\"; Source = \"content\\resept_ico.bmp\";};";
String startingBracePattern = Pattern.quote("{");
String endBracePattern = Pattern.quote("}");
s=s.replaceAll(Pattern.quote("\\"), "\\\\\\\\"); //Replacing all the single \ with double \\
s = s.replaceAll("\\s*"+startingBracePattern +"\\s*", "\\{\""); //Replacing all the `spaces { spaces` with `{"` MEANS all the { to replace with {"
s = s.replaceAll(";\\s*"+endBracePattern +"\\s*;", "\\};"); //Replacing all the `; spaces } spaces ;` with `},"` MEANS all the ;}; to replace with };
s = "{\"" + s.substring(0, s.length() - 1) +"}"; //Removing last ; and appending {" and }
s = s.replaceAll("\\s*:", "\":"); // Replacing all the `space with :` with `":`
s = s.replaceAll("\\s*;\\s*", ",\""); //Replacing all the `spaces ; spaces` with `,"`
s = s.replaceAll("\\s*=\\s*", "\":"); //Replacing all the `spaces = spaces` with `":`
Gson gson = new Gson();
MyVer newObj = gson.fromJson(s, MyVer.class);
}
This converts and give you the object of MyVer and then you can access all the variables.
NOTE: You can alter the code little to replace all \r\n if they are present in your input variables. I have not used them and your actual data supplied in question in a single line for simplicity.
JSON sounds a lot easier in this case..
.. however, if you were to do this using regular expressions, one way would be:
for the simple cases (eg. version):
// look for Version: some stuff ;
Pattern versionPattern = Pattern.compile("Version\\s*:\\s*\"\\w+\"\\s*;");
// the whole big string you're looking in
String bigString = ...; // the entire string from before can go here
// create a matcher for the "version pattern"
Matcher versionMatcher = versionPattern.matcher(bigString);
// check if there's a match in the string
if(versionMatcher.find()) {
// get the matching substring
String matchingSubstring = bigString.substring(
versionMatcher.start(),
versionMatcher.end()
);
// we need the area between the quotes
String version = matchingSubstring.split("\"")[1];
// do something with it
...
}
for the harder (multi-line) cases (eg. UserConfig):
// look for UserConfig : { some stuff };
Pattern userconfigPattern = Pattern.compile("UserConfig\\s*:\\s*{[^}]*};", Pattern.DOTALL);
// create a matcher for the "user config pattern"
Matcher userconfigMatcher = userconfigPattern.matcher(bigString);
// check if there's a match in the string
if(userconfigMatcher.find()) {
// get the matching substring
String matchingSubstring = bigString.substring(
userconfigMatcher.start(),
userconfigMatcher.end()
);
// we need the area between the curly braces
String version = matchingSubstring.split("[{}]")[1];
// do something with it
...
}
EDIT: this is probably an easier way
// split the input string into fields
String[] fields = bigString.split("[^:]+:([^{;]+;)|({[^}]+};)");
// for each key-value pair
for(String field : fields) {
// the key and value are separated by colons
String parts = field.split(":");
String key = parts[0];
String value = parts[1];
// do something with them, or add them to a map
...
}
This last way splits the input string based on the assumption that each key-value pair consists of:
some (non-colon) characters at the start, followed by
a colon,
either
-> some characters that are not curly braces or semi-colons (for simple attributes), or
-> curly braces containing some characters that are not curly braces
a semi-colon
Here is json solution
str = "{" + str.substring(0, str.lastIndexOf(";")).replace(";\n}", "}") + "}";
try {
JSONObject json = new JSONObject(str);
String version = json.getString("Version");
JSONObject config = json.getJSONObject("UserConfig");
String source = config.getString("Source");
} catch (JSONException e) {
e.printStackTrace();
}
since ";" should not be in front of "}"
Source = "content\\resept_ico.bmp";
}
we need remove them