Parse a line using split method in Java - java

request = GET /solr1/select?q=reqRelDate_l%3A%5B1321516800000+TO+1321775940000%5D+AND+requestStatus_s%3ASUB29&wt=javabin&version=1 HTTP/1.1
or
request = GET /solr1/select?q=reqRelDate_l%3A%5B1321516800000+TO+1321775940000%5D+AND+requestStatus_s%3ASUB29&wt=javabin&version=1 HTTP/1.1
And I want to get all the data of &fq= So in the first case &fq= contains
doctype_s%3Acom.host.ems.qsrr.SurveyInstance
fq=%21survey_id_l%3A%2829%29
So I want filter should contain the value starting from first &fq= meaning that filter should contain the below value for the first case. And request can have many &fq= so I want filter to have value starting from &fq=
doctype_s%3Acom.host.ems.qsrr.SurveyInstance&fq=%21survey_id_l%3A%2829%29
So if I do by this way-- then I get only first value of &fq= not other value.. So what's the best way to get all the value starting from first &fq= and replacing these thing &wt=javabin&version=1 HTTP/1.1
filter = request.split("&fq=")[1];
I need to parse the above request string so that I can get the value of &fq= in the filter variable..

Off the top of my head I guess you could do something like this:
String[] params = request.split("&");
List<String> values = new ArrayList<String>();
for (int i = 0; i < params.length; i++) {
if (params[i].startsWith("fq")) {
String[] fqsplit = params[i].split("=");
if (fqsplit.length > 1) {
values.add(fqsplit[1]);
}
}
}
Now you will have a List with all the values of the fq parameters.
Sure I could come up with something more clever.

If there is always another &VAR following &fq=, you can do:
String fq_stuff = filter.split("&")[0];

If it is truly the first instance of fq, why not be simple?? I really think all these splits and regexs are overkill sometimes.
int firstFQ = request.indexOf("&fq");
if (firstFQ < 0)
throw new SomeException();
int nextAmp = request.indexOf("&", firstFQ+1);
if (nextAmp < 0)
throw new SomeException();
return request.subString(firstFQ+3, nextAmp); // I may have an off by 1 error here
You can clean this up by making "&fq" a nice constant or an arg passed in.

Related

Is there a way to select specific characters from a TextView variable?

I am using AWS IoT to read and publish some information from a microelectronic's sensors. I am able to get the json file in the app as a big wall of text, but it is not very readable. I am using TextView as I don't want the user to be able to change the information. My problem is that I can't find a way to remove the parts that are not necessary to the user.
I am new to app creation, so I am trying to do this as simply as possible. I have my xml ready to receive the information; I just need the info in a variable that I can pass to it. I have tried implementing a character array, but haven't been able to get past the fact that I can't edit the text view.
tvLastMessage = (TextView) findViewById(R.id.tvLastMessage);
This is currently the block of text that I am receiving. It looks like this:
{"sensors":[{"name":"steamTemp","data":"181.39","state":1,
{"name":"waterTemp","data":"-713.15","state":0,
{"name":"waterFlow","data":"0.00","state":3,
{"name":"dieselFlow","data":"0.00","state":2,
{"name":"manualResetLevel","data":"1","state":0,
{"name":"waterFeederLevel","data":"1","state":0,
{"name":"autoResetPressure","data":"1","state":0,
{"name":"manualResetPressure","data":"1","state":0},
{"name":"tempLimit","data":"1","state":0,
{"name":"heatEff","data":"0.00","state":2}]}
The text does not look as formatted as this, but it is more understandable and readable to represent it this way. It normally does not have the new lines, so it will just naturally go to one as it runs out of room.
I am hoping that I can get it to simply show the numbers associated with each "name" and "data" as I have those hard-coded into my xml since they don't change. Just getting those numbers into different variables would be ideal, so I can simply reference the variable in my xml file. However, if there is a better way to do this, I am happy to take suggestions!
Try using a loop to find each instance of "name", "data", and "state", and get the values between them.
Assuming input is a string:
String string = "{\"sensors\":[{\"name\":\"steamTemp\",\"data\":\"181.39\",\"state\":1,\n{\"name\":\"waterTemp\",\"data\":\"-713.15\",\"state\":0,\n{\"name\":\"waterFlow\",\"data\":\"0.00\",\"state\":3,\n{\"name\":\"dieselFlow\",\"data\":\"0.00\",\"state\":2,\n{\"name\":\"manualResetLevel\",\"data\":\"1\",\"state\":0,\n{\"name\":\"waterFeederLevel\",\"data\":\"1\",\"state\":0,\n{\"name\":\"autoResetPressure\",\"data\":\"1\",\"state\":0,\n{\"name\":\"manualResetPressure\",\"data\":\"1\",\"state\":0},\n{\"name\":\"tempLimit\",\"data\":\"1\",\"state\":0,\n{\"name\":\"heatEff\",\"data\":\"0.00\",\"state\":2}]}";
Map<String, Double> map = new HashMap<>();
int index0 = 0, index1, index2;
while (true) {
// Get indices
index0 = string.indexOf("name", index0);
index1 = string.indexOf("data", index0);
index2 = string.indexOf("state", index1);
// If "name", "data", or "state" was not found
if (index0 == -1 || index1 == -1 || index2 == -1)
break;
// Get the data from the string and put it into the map
String key = string.substring(index0 + 7, index1 - 3);
Double value = Double.parseDouble(string.substring(index1 + 7, index2 - 3));
map.put(key, value);
// Update index
index0 = index2;
}
System.out.println(map);
Output:
{waterFlow=0.0, manualResetLevel=1.0, waterFeederLevel=1.0, manualResetPressure=1.0, waterTemp=-713.15, autoResetPressure=1.0, tempLimit=1.0, dieselFlow=0.0, heatEff=0.0, steamTemp=181.39}

Java android - How to split string data with empty data inside of it

I have a data string name stringSplit that I want to split into 5 parts.
I use this to split the String:
String[] pisah = stringSplit.split(",", -1);
for (int i=0;i< pisah.length;i++) {
String hasil1 = pisah[0];
String hasil2 = pisah[1];
String hasil3 = pisah[2];
String hasil4 = pisah[3];
String hasil5 = pisah[4];
}
When the value in stringSplit there are 5 data (f.e: “data1,data2,data3,data4,data5”), the code is working properly. But when in stringSplit there are only one, two or three data, an exception will caught:
(f.e: java.lang.ArrayIndexOutOfBoundsException: length=4; index=4).
And my question is how to handle the empty string? So even though the data only one, two, or three data the stringSplit still can be splitted.
I've tried by adding limit to -1 which this solution I got from another post, but still not working for me.
Editted:
I almost forgot, the result string (hasil1 - hasil5) will use for edittext.
fe: editText1.setText(hasil1);
and others.
One possible solution is to check if the index you are looking for is less than the length of the array. If that index is less than the size of the array than it definitely exists.
for (int i=0;i< pisah.length;i++) {
if(0 < pisah.length)
String hasil1 = pisah[0];
if(1 < pisah.length)
String hasil2 = pisah[1];
//similarly for all other idexes that you want the value for.
}
You have hard coded the number of EditText fields you can have! What if, there is a change in requirement, where you have to add another field? That would need you to add "editText6" and "hasil6" at a lot of places. The code is not nimble footed to changes in specs.
This is what I would do.
Create a list of EditText, say, textList
Iterate over the pisah array, and textist simultaneously and add the String at index i in pisah to the EditText object at index i in
textList.
This way, in case there are only 3 data values, you are automatically taking care of populating only 3 EditText objects.
This is the code :
List<EditText> textList;
String[] pisah = stringSplit.split(",", -1);
for (int i=0;i< pisah.length;i++) {
textList.get(i).setTest(pisah[i]);
}
use this code:
String res[] = new String[5];
String[] pisah = stringSplit.split(",");
for (int i=0;i< pisah.length && i < res.length;i++) {
res[i] = pisah[i];
}
if(res[0] != null )
//.......... res[0] valid
if(res[1] != null )
//.......... res[1] valid
if(res[2] != null )
//.......... res[2] valid
if(res[3] != null )
//.......... res[3] valid
if(res[4] != null )
//.......... res[4] valid
Here is the problem,
for (int i=0;i< pisah.length;i++) {
String hasil1 = pisah[0];
String hasil2 = pisah[1];
String hasil3 = pisah[2];
String hasil4 = pisah[4];
String hasil5 = pisah[5];
}
but that iterates over the list and gets the values in the list from 0-5 every time it loops, so what you should be doing is something like this
for(int i = 0; i < 6; i++){
if(i >= pisah.length()) break;
String hasilI = pisah[i];
}
This iterates over the list 6 times then if the list's size < 6 it will break out of the loop

String naming convention in java

I am currently trying to make a naming convention. The idea behind this is parsing.
Lets say I obtain an xml doc. Everything can be used once, but these 2 in the code below can be submitted several times within the xml document. It could be 1, or simply 100.
This states that ItemNumber and ReceiptType will be grabbed for the first element.
ItemNumber1 = eElement.getElementsByTagName("ItemNumber").item(0).getTextContent();
ReceiptType1 = eElement.getElementsByTagName("ReceiptType").item(0).getTextContent();
This one states that it will grab the second submission if they were in their twice.
ItemNumber2 = eElement.getElementsByTagName("ItemNumber").item(1).getTextContent();
ReceiptType2 = eElement.getElementsByTagName("ReceiptType").item(1).getTextContent();
ItemNumber and ReceiptType must both be submitted together. So if there is 30 ItemNumbers, there must be 30 Receipt Types.
However now I would like to set this in an IF statement to create variables.
I was thinking something along the lines of:
int cnt = 2;
if (eElement.getElementsByTagName("ItemNumber").item(cnt).getTextContent();)
**MAKE VARIABLE**
Then make a loop which adds one to count to see if their is a third or 4th. Now here comes the tricky part..I need them set to a generated variable. Example if ItemNumber 2 existed, it would set it to
String ItemNumber2 = eElement.getElementsByTagName("ItemNumber").item(cnt).getTextContent();
I do not wish to make pre-made variable names as I don't want to code a possible 1000 variables if that 1000 were to happen.
KUDOS for anyone who can help or give tips on just small parts of this as in the naming convention etc. Thanks!
You don't know beforehand how many ItemNumbers and ReceiptTypes you'll get ? Maybe consider using two Lists (java.util.List). Here is an example.
boolean finished = ... ; // true if there is no more item to process
List<String> listItemNumbers = new ArrayList<>();
List<String> listReceiptTypes = new ArrayList<>();
int cnt = 0;
while(!finished) {
String itemNumber = eElement.getElementsByTagName("ItemNumber").item(cnt).getTextContent();
String receiptType = eElement.getElementsByTagName("ReceiptType").item(cnt).getTextContent();
listItemNumbers.add(itemNumber);
listReceiptTypes.add(receiptType);
++cnt;
// update 'finished' (to test if there are remaining itemNumbers to process)
}
// use them :
int indexYouNeed = 32; // for example
String itemNumber = listItemNumbers.get(indexYouNeed); // index start from 0
String receiptType = listReceiptTypes.get(indexYouNeed);

Null Pointer that makes no sense to me?

Im currently working on a program and any time i call Products[1] there is no null pointer error however, when i call Products[0] or Products[2] i get a null pointer error. However i am still getting 2 different outputs almost like there is a [0] and 1 or 1 and 2 in the array. Here is my code
FileReader file = new FileReader(location);
BufferedReader reader = new BufferedReader(file);
int numberOfLines = readLines();
String [] data = new String[numberOfLines];
Products = new Product[numberOfLines];
calc = new Calculator();
int prod_count = 0;
for(int i = 0; i < numberOfLines; i++)
{
data = reader.readLine().split("(?<=\\d)\\s+|\\s+at\\s+");
if(data[i].contains("input"))
{
continue;
}
Products[prod_count] = new Product();
Products[prod_count].setName(data[1]);
System.out.println(Products[prod_count].getName());
BigDecimal price = new BigDecimal(data[2]);
Products[prod_count].setPrice(price);
for(String dataSt : data)
{
if(dataSt.toLowerCase().contains("imported"))
{
Products[prod_count].setImported(true);
}
else{
Products[prod_count].setImported(false);
}
}
calc.calculateTax(Products[prod_count]);
calc.calculateItemTotal(Products[prod_count]);
prod_count++;
This is the output :
imported box of chocolates
1.50
11.50
imported bottle of perfume
7.12
54.62
This print works System.out.println(Products[1].getProductTotal());
This becomes a null pointer System.out.println(Products[2].getProductTotal());
This also becomes a null pointer System.out.println(Products[0].getProductTotal());
You're skipping lines containing "input".
if(data[i].contains("input")) {
continue; // Products[i] will be null
}
Probably it would be better to make products an ArrayList, and add only the meaningful rows to it.
products should also start with lowercase to follow Java conventions. Types start with uppercase, parameters & variables start with lowercase. Not all Java coding conventions are perfect -- but this one's very useful.
The code is otherwise structured fine, but arrays are not a very flexible type to build from program logic (since the length has to be pre-determined, skipping requires you to keep track of the index, and it can't track the size as you build it).
Generally you should build List (ArrayList). Map (HashMap, LinkedHashMap, TreeMap) and Set (HashSet) can be useful too.
Second bug: as Bohemian says: in data[] you've confused the concepts of a list of all lines, and data[] being the tokens parsed/ split from a single line.
"data" is generally a meaningless term. Use meaningful terms/names & your programs are far less likely to have bugs in them.
You should probably just use tokens for the line tokens, not declare it outside/ before it is needed, and not try to index it by line -- because, quite simply, there should be absolutely no need to.
for(int i = 0; i < numberOfLines; i++) {
// we shouldn't need data[] for all lines, and we weren't using it as such.
String line = reader.readLine();
String[] tokens = line.split("(?<=\\d)\\s+|\\s+at\\s+");
//
if (tokens[0].equals("input")) { // unclear which you actually mean.
/* if (line.contains("input")) { */
continue;
}
When you offer sample input for a question, edit it into the body of the question so it's readable. Putting it in the comments, where it can't be read properly, is just wasting the time of people who are trying to help you.
Bug alert: You are overwriting data:
String [] data = new String[numberOfLines];
then in the loop:
data = reader.readLine().split("(?<=\\d)\\s+|\\s+at\\s+");
So who knows how large it is - depends on the success of the split - but your code relies on it being numberOfLines long.
You need to use different indexes for the line number and the new product objects. If you have 20 lines but 5 of them are "input" then you only have 15 new product objects.
For example:
int prod_count = 0;
for (int i = 0; i < numberOfLines; i++)
{
data = reader.readLine().split("(?<=\\d)\\s+|\\s+at\\s+");
if (data[i].contains("input"))
{
continue;
}
Products[prod_count] = new Product();
Products[prod_count].setName(data[1]);
// etc.
prod_count++; // last thing to do
}

How many items can send in one amazon request?

I try to get ASIN for movies in my DB, try to match via EAN. I created simple java class to connect with Amazon:
AWSECommerceServiceservice = new AWSECommerceService();
service.setHandlerResolver(new AwsHandlerResolver(AMAZON_SECRET_KEY));
AWSECommerceServicePortType port = service.getAWSECommerceServicePortDE();
Holder<OperationRequest> operationrequest = new Holder<OperationRequest>();
failedItem = 0;
doneItem = 0;
ItemLookup lookup = new ItemLookup();
lookup.setAWSAccessKeyId(AMAZON_ACCESS_ID);
lookup.setAssociateTag(ASSOCIATE_TAG);
ItemLookupRequest request = new ItemLookupRequest();
request.getResponseGroup().add("ItemAttributes");
request.setSearchIndex("Video");
request.setIdType("EAN");
//Here iterates on my amazon-movies object
for (AmazonSIdN i : amazonItems) {
request.getItemId().add(i.getEan());
if (request.getItemId().size() % 10 == 0) { //numbers of items in request
LOG.info("Request size = " + request.getItemId().size());
break;
}
}
Holder<List<Items>> items = new Holder<List<Items>>();
lookup.getRequest().add(request);
port.itemLookup(lookup.getMarketplaceDomain(), lookup.getAWSAccessKeyId(),
lookup.getAssociateTag(),lookup.getXMLEscaping(), lookup.getValidate(),
lookup.getShared(), lookup.getRequest(),operationrequest, items);
List<Items> result = items.value;
for (int k = 0; k < result.get(0).getItem().size(); ++k) {
Item i = result.get(0).getItem().get(k);
//do something with item
}
It is working, but one thing is really strange for me. When in this line:
if (request.getItemId().size() % 10 == 0) { //numbers of items in request
I use 40 000 instead of 10 WS returns:
The server sent HTTP status code 413: Request Entity Too Large
And this is understandable. But when I put number greater then 10 WS doesn't return eny errors but result has no items:
Can anybody tell me what I a'm doing wrong or what did I forget set? Any advice?
I found an answer, so I put it here maybe someone save some time in future.
In Amazon ItemLookup documentatnion is written:
ItemId - One or more (up to ten) positive integers that uniquely identify an item. The meaning of the number is specified by IdType. That is, if IdType is ASIN, the ItemId value is an ASIN. If ItemIdis an ASIN, a search index cannot be specified in the request.
Type: String
Default: None
Constraints: Must be a valid item ID. For more than one ID, use a comma-separated list of up to ten IDs.

Categories

Resources