I am trying to write an Android Application in Java for an Android phone. The Android application reads serial data strings via Bluetooth using SPP profile. These strings are sent by another Bluetooth device. These strings are in the following format:
"Acc Data:x_adc,y_adc,z_adc!"
Each string begins with:
"Acc Data:
and ends with
"!"
The x_adc, y_adc and z_adc are values and have a length of 5 digits.
These strings are sent at regular intervals. Right now I am able to use InputStream to accept these strings using a string buffer. I'm also able to display the complete strings in a scrollable TextView which displays each string beneath the other.
What I want to do is to decompose the x_adc, y_adc and z_adc values from the strings and display these values in a 3 separate TextViews. The TextViews which need to display the adc values have to refresh after a new string has been sent to the Android smartphone. I tried to use the Pattern class and split() to decompose the strings but failed to understand them and use them in the application.
Could someone help me with this problem?
You could use substring() to clean the extra data, and then split():
String[] values = indata.substring(9, 26).split(",");
String x_adc = values[0];
...
Try:
private TextView tv1;
private TextView tv2;
private TextView tv3;
update("Acc Data:x_adc,y_adc,z_adc!");
public void update(String data) {
String values[] = data.replace("Acc Data:", "").replace("!", "").split(",");
String v1 = "";
String v2 = "";
String v3 = "";
if(values != null && values.length == 3) {
v1 = values[0];
v2 = values[1];
v3 = values[2];
}
tv1.setText(v1);
tv2.setText(v2);
tv3.setText(v3);
}
Alternate way of getting the values:
String values[] = data.substring(data.indexOf(':') + 1, data.indexOf('!')).split(",");
Just have a lood at the String functions substring(beginIndex, endIndex) to suppress the static part of the string and split(",") to get the 3 values.
This code will handles instances where > 3 tokens are included in the String.
public static void main(String[] args) {
String value = "Acc Data:x_adc,y_adc,z_adc!";
String trimmed = value.substring(value.indexOf(":")+1, value.length()-1);
String[] tokens = trimmed.split(",");
for(String token: tokens){
System.out.println(token);
}
}
Related
A method replacement replaces all names (from given String a) in [Name] or {Name} brackets, with telephone numbers if [] these brackets, or e-mails if {} these brackets. The address book is represented with array tel, whose elements can be "Tel Name telephoneNumber" or "Mail Name mail". For example if input is: "You can contact jake via phone number [Jake] or via email {Jake}", output should be "You can contact jake via phone number +12345 or via email jake#gmail.com", and tel elements are "Tel Jake +12345" and "Mail Jake jake#gmail.com". If the given name does not exist in address book do nothing with the string. The problem that I have is when it comes to replacing substrings I use method replaceFirst which will replace the first occurrence of the substring that I want to replace.
Maybe the shorter question would be how to replace specific part of string?
public static String replacement(String a, String[] tel) {
for (int i = 0; i<a.length()-1; i++) {
char c = a.charAt(i);
if (c=='[') {
int ind = a.indexOf(']', i);
String name = a.substring(i+1, ind);
for (int j=0; j<tel.length; j++) {
int ind1 = tel[j].indexOf(' ', 4);
String name1 = tel[j].substring(4, ind1);
String p = tel[j].substring(0,3);
String help = "Tel";
int temp = p.compareTo(help);
if (ime.equals(ime1)==true && temp==0) {
String telephone = tel[j].substring(ind1+1, tel[j].length());
a = a.replaceFirst(name, telephone);
}
}
}
if (c=='{') {
int ind = a.indexOf('}', i);
String name = a.substring(i+1, ind);
for (int j=0; j<tel.length; j++) {
int ind1 = tel[j].indexOf(' ', 5);
String name1 = tel[j].substring(5, ind1);
String p = tel[j].substring(0,4);
if (name.equals(name1) && p.compareTo("Mail")==0) {
String mail = tel[j].substring(ind1+1, tel[j].length());
a = a.replaceFirst(name, mail);
}
}
}
}
return a;
}
Main:
String a = "In NY you can contact peter via telephone number [Peter] or e-mail {Peter}. In London you can contact anna via telephone number [Anna] or e-mail {Anna}."
+ "In Chicago you can contact shawn via telephone number [Shawn] or e-mail {Shawn}";
String [] tel = {"Mail Peter peter#gmail.com", "Tel Anna +3456","Tel Shawn +1234", "Mail Shawn shawn#yahoo.com"};
String t = replacement(a,tel);
System.out.println(t);
Console:
In NY you can contact peter via telephone number [peter#gmail.com] or e-mail {peter#gmail.com}.
In London you can contact anna via telephone number [+3456] or e-mail {Anna}.In Chicago you can
contact shawn via telephone number [+1234] or e-mail {shawn#yahoo.com}
Instead of encoding the type of the data (email vs phone number) and the replacement key into strings, I would put the data into separate variables and ues data structures like Map:
Map<String, String> tel = Map.of("Anna", "+3456", "Shawn", "+1234");
Map<String, String> mail = Map.of("Peter", "peter#gmail.com", "Shawn", "shawn#yahoo.com");
String t = replacement(a, tel, mail);
The replacement function could use a regular expression to find the substrings that match the key words you want to replace [something] and {something}. It would check which one it found, and add a replacement using the telephone or email it finds in the map data structure.
private static String replacement(String a, Map<String, String> tel, Map<String, String> mail) {
Pattern compile = Pattern.compile("\\{(.*?)\\}|\\[(.*?)\\]");
Matcher matcher = compile.matcher(a);
StringBuilder sb = new StringBuilder();
// Find substrings matching {something} and [something]
while (matcher.find()) {
String matched = matcher.group(0);
// Which was it, { or [ ?
if (matched.charAt(0) == '{') {
// Email. Replace from "mail"
String emailAddress = mail.getOrDefault(matcher.group(1), matched);
matcher.appendReplacement(sb, emailAddress);
} else if (matched.charAt(0) == '[') {
// Telephone. Replace from "tel"
String phoneNumber = tel.getOrDefault(matcher.group(2), matched);
matcher.appendReplacement(sb, phoneNumber);
}
}
matcher.appendTail(sb);
return sb.toString();
}
Handling of strings in a specified format is done best using regular expressions. You define a specified pattern and after you find a part matching your pattern, you can replace it or analyze further.
It's best to write your code to make it easily extensible. For example - if a new contact form is added (home address, fax, business phone number), it should be easy to handle it in the code. Your solution makes it harder to resolve such problems as a whole new if branch is required and it's easy to make a mistake, it also makes the code less readable.
When dealing with a kind of dictionary (like your input String array), it's worth using a Map as it makes the processing faster and the code more readable. When a constant values are present, it's worth to define them too - as constants or enum values. Also - Java allows for writing more functional and more readable, functional-style code instead of nested for-eaches - it's worth using those features (JDK8+).
Please, find the code snippet below and a whole project with tests comparing your solution to mine on GitHub - you can view it there or clone the repository and verify the code yourself:
// we can simply add new contact types and their matchers using the constant below
private static final Map<Pattern, ContactType> CONTACT_PATTERNS = Map.of(
Pattern.compile("\\[(\\S+)]"), ContactType.TEL,
Pattern.compile("\\{(\\S+)}"), ContactType.MAIL
);
#Override
public String replace(String input, String[] dictionary) {
// we're mapping the dictionary to make it easier to use and more readable (also in debugging)
Map<ContactType, Map<String, String>> contactTypeToNameToValue =
Arrays.stream(dictionary)
.map(entry -> entry.split(" ")) // dictionary entry is split by ' ' character
.collect(groupingBy(entry -> ContactType.fromString(entry[0]), // first split part is the contact type
toMap(entry -> entry[1], // second part is the person's name
entry -> entry[2]))); // third part is the contact value
String output = input;
for (Map.Entry<Pattern, ContactType> entry : CONTACT_PATTERNS.entrySet()) {
Pattern pattern = entry.getKey();
ContactType contactType = entry.getValue();
output = pattern.matcher(output)
.replaceAll(matchResult -> {
String name = matchResult.group(1);
// we search our dictionary and get value from it or get the original value if nothing matches given name
return Optional.ofNullable(contactTypeToNameToValue.get(contactType))
.map(nameToValue -> nameToValue.get(name))
.orElseGet(matchResult::group);
});
}
return output;
}
public enum ContactType {
TEL,
MAIL;
private static ContactType fromString(String value) {
return Arrays.stream(values())
.filter(enumValue -> enumValue.name().equalsIgnoreCase(value))
.findFirst()
.orElseThrow(RuntimeException::new);
}
}
I'm trying to split a specific String of the format
0001,0004,dd/mm/yy hh:mm:ss,01,value01,value02;
in order to extract and save value01 and value02. How can I do this?
Here is what i tried so far:
//buffer contains a String like: "0001,0004,dd/mm/yy hh:mm:ss,01,18,750"
String string = new String(buffer,0,len);
String[] parts = string.split(",");
String temp = parts[5];
String lum = parts[6];
System.out.print(temp);
System.out.print(lum);
With this code I get ArrayIndexOutofBounds when running the program in Netbeans.
Image of error description
Also tried this method:
//buffer contains a String like: "0001,0004,dd/mm/yy hh:mm:ss,01,18,750"
String s= new String(buffer,0,len);
String aux = s + ",";
String[] dados = aux.split(",");
float valor1 = Float.parseFloat(dados[5]);
float valor2 = Float.parseFloat(dados[6]);
System.out.print(aux);
This:
String temp = parts[5];
String lum = parts[6];
Should be this:
String temp = parts[4];
String lum = parts[5];
Remember that arrays in Java are zero-based. So if you do this:
String[] parts = "0001,0004,dd/mm/yy hh:mm:ss,01,value01,value02".split(",");
Then "0001" would be in parts[0], "0004" in parts[1], "value01" in parts[4] etc.
Achieving what you're trying to do is acutally pretty easy.
Assuming that your string really always looks like:
0001,0004,dd/mm/yy hh:mm:ss,01,value01,value02;
Just cut off the start of the string which you don't need and extract the values afterwards:
// This can be done in hundreds of ways, for the sake of simplicity i'll use substring
String s ="0001,0004,dd/mm/yy hh:mm:ss,01,value01,value02;";
String cutOff = s.substring(31, s.length()-1);
String[] results = cutOff.split(",");
please find below code. It has just a bit modification in Andrew's code. Since we are storing the string after splitting into a String array and it's obvious that array index starts with 0. That's why in order to get value01 and value02, we should use index 4 and 5.
public class JavaApplication1
{
public static void main(String[] args)
{
String str="0001,0004,dd/mm/yy hh:mm:ss,01,value01,value02";
String [] strArr=str.split(",");
String temp=strArr[4];
String lum=strArr[5];
System.out.println(temp);
System.out.println(lum);
}
}
I was working on a task to parse a cucumber feature string where I need to split string into 5 like the following.
String data = "calls 'create' using 'POST' on some uri";
I was implementing the basic split functionality multiple times (without any regex which is very tedious) to generate the data into the following.
String dataArray[] = {"calls '","create","' using '","POST", "' on some uri"};
I wanted to obtain the names of dataArray[1] and dataArray[3]. Is there a way to generate the above dataArray using regex and split or some other straight forward method?
Simply use this?
String dataArray[] = data.split("'");
->
[calls , create, using , POST, on some uri]
Here is a solution which use Regex:
public static void main (String[] args) {
String data = "calls 'create' using 'POST' on some uri";
String[] dataArray = new String[2];
Matcher matcher = Pattern.compile("'[a-zA-Z]+'").matcher(data);
int counter = 0;
while (matcher.find()) {
String result = matcher.group(0);
dataArray[counter++] = result.substring(1, result.length() - 1);
}
}
Output:
dataArray[0] --> create
dataArray[1] --> POST
I can have this string as below :
String s = "chapterId=c_1§ionId=s_24666&isHL=1&cssFileName=haynes";
or
String s = "chapterId=c_1§ionId=s_24666";
I need to get the number ("24666" in the examples).
String res = s.substring(s.lastIndexOf("s_")+ 2) this returns me the number + chars till the end of the string(the second example is ok). But I need to stop after the number ends. How can I do that.? Thanks
You can use regExp
String s = "chapterId=c_1§ionId=s_24666";
//OR
//String s = "chapterId=c_1§ionId=s_24666&isHL=1&cssFileName=haynes";
s=s.replaceAll(".*?s_(\\d+).*","$1");
System.out.println(s);
OUTPUT:
24666
Where,
.*?s_ means anything before s_ (s_ inclusive)
(\\d+) means one or more digits () used for group
$1 means group 1 which is digits after s_
Note:Assumed that your every string follows specific format which includes s_ and number after s_.
You can split the string by the character & to get the parameters, and split each parameter with the = to get the parameter name and parameter value. And now look for the parameter name "sectionId", and cut the first 2 characters of its value to get the number, and you can use Integer.parseInt() if you need it as an int.
Note that this solution is flexible enough to process all parameters, not just the one you're currently interested in:
String s = "chapterId=c_1§ionId=s_24666&isHL=1&cssFileName=haynes";
String[] params = s.split("&");
for (String param : params) {
String[] nameValue = param.split("=");
if ("sectionId".equals(nameValue[0])) {
int number = Integer.parseInt(nameValue[1].substring(2));
System.out.println(number); // Prints 24666
// If you don't care about other parameters, this will skip the rest:
break;
}
}
Note:
You might want to put Integer.parseInt() into a try-catch block in case an invalid number would be passed from the client:
try {
int number = Integer.parseInt(nameValue[1].substring(2));
} catch (Exception e) {
// Invalid parameter value, not the expected format!
}
Try this:
I use a check in the substring() method - if there is no "&isHL" in the string (meaning its type 2 you showed us), it will just read until the string ends. otherwise, it will cut the string before the "&isHL". Hope this helps.
Code:
String s = "chapterId=c_1§ionId=s_**24666**";
int endIndex = s.indexOf("&isHL");
String answer = s.substring(s.lastIndexOf("s_") + 2, endIndex == -1 ? s.length() : endIndex);
Try following:
String s = "chapterId=c_1§ionId=s_24666&isHL=1&cssFileName=haynes";
String tok[]=s.split("&");
for(String test:tok){
if(test.contains("s_")){
String next[]=test.split("s_");
System.out.println(next[1]);
}
}
Output :
24666
Alternatively you can simply remove all other words if they are not required as below
String s="chapterId=c_1§ionId=s_24666&isHL=1&cssFileName=haynes";
s=s.replaceAll(".*s_(\\d+).*","$1");
System.out.println(s);
Output :
24666
The dig over here is splitting your string using a Regular Expression to further divide the string into parts and get what is required. For more on Regular Expressions visit this link.
You could sue this regex : (?<=sectionId=s_)(\\d+) This uses positive look-behind.
demo here
Following code will work even if there is multiple occurrence of integer in given string
String inputString = "chapterId=c_a§ionId=s_24666&isHL=1&cssFileName=haynes_45";
String[] inputParams = inputString.split("&");
for (String param : inputParams)
{
String[] nameValue = param.split("=");
try {
int number = Integer.parseInt(getStringInt(nameValue[1]));
System.out.println(number);
}
catch(IllegalStateException illegalStateException){
}
}
private String getStringInt(String inputString)
{
Pattern onlyInt = Pattern.compile("\\d+");
Matcher matcher = onlyInt.matcher(inputString);
matcher.find();
String inputInt = matcher.group();
return inputInt;
}
OUTPUT
2466
1
45
Use split method as
String []result1 = s.split("&");
String result2 = tempResult[1];
String []result3 = result2.split("s_");
Now to get your desire number you just need to do
String finalResult = result3[1];
INPUT :
String s = "chapterId=c_1§ionId=s_24666&isHL=1&cssFileName=haynes";
OUPUT :
24666
A MySQL table called item_list has a field named description, the problem is the previous programmer combined the name and description of the item in one field called description. The data is now at 20k+. Now I am going to have a problem during migration.So how do I separate one
String description="BEARING, ROLLER 23230CKE4 SPHERICAL"
into two new strings
String name="BEARING"
String description="ROLLER 23230CKE4 SPHERICAL"
Any help will be appreciated.
you can try this way
String description="BEARING, ROLLER 23230CKE4 SPHERICAL";
String [] arr=description.split(",");
System.out.println(arr[0]);
System.out.println(arr[1]);
output
BEARING
ROLLER 23230CKE4 SPHERICAL
String Split methods returns an array of strings.As in the String description has one comma(,) So the whole string will be splited into 2 strings.
You can use StringTokenizer
something like this
StringTokenizer st = new StringTokenizer(description,",");
String name=st.nextToken();
description=st.nextToken();
Unfortunately string split functions will not work correctly if there is more than 1 , in the combined string.
I recommend you split on the first , only.
int idx = description.indexOf(',');
if (idx != -1) { // if there is a comma
name = description.substring(0, idx);
description = description.substring(idx+1);
} else {
???? // no comma in description
}
combination of all the answers.., that solve the problem.
String name="",new_d ="";
String description="BEARING, ROLLER 23230CKE4 SPHERICAL";
int idx = description.indexOf(',');
if (idx != -1) { // if there is comma
String arr[]=description.split(",\\s*");
name=arr[0].toString();
new_d=arr[1].toString();
}
else {
// if there is no comma
name=description;
new_d="";
}
System.out.println(name);
System.out.println(new_d);