NumberFormatException: unable to parse '' as integer - java

I have a date string:
gridcell.setTag(theday + "-" + themonth + "-" + theyear + "|" + hijri_day + "-" + hijri_month + " ("+ hijri_monthno +") " + hijri_year);
..which I pass on to another class on button click if the date has an event:
String date_month_year = (String) view.getTag();
if (isHoliday(d, m, y))
{
Intent i = new Intent(view.getContext(), Events.class);
i.putExtra("date_string", date_month_year);
startActivity(i);
}
In the Events.class, I get the parameters:
Intent intent = getIntent();
String date_string = intent.getStringExtra("date_string");
date_view = (TextView) this.findViewById(R.id.hijridate);
eventdetails = (TextView) this.findViewById(R.id.eventdetails);
date_view.setText(date_string);
String[] dateAr = date_string.split("-|\\||\\(|\\)|\\s+");
m = Integer.parseInt(dateAr[6]);
d = Integer.parseInt(dateAr[3]);
y = Integer.parseInt(dateAr[8]);
This is the Hijri month array:
private String months[] = {"Muharram","Safar","Rabi-al Awwal","Rabi-al Thani","Jumada al-Ula","Jumada al-Thani","Rajab","Sha\'ban","Ramadhan","Shawwal","Dhul Qa\'dah","Dhul Hijjah"};
The problem I'm having is that when it's a one word month name (i.e. Muharram, Safar, Rajab, etc. .) everything works smoothly. However, if it's a word with a space or a dash (i.e. Rabi-al awwal, Dhul Hijjah), it throws the error: NumberFormatException: unable to parse '' as integer or NumberFormatException: unable to parse 'al' as integer
What am I doing wrong?

Is there a reason you need to use a lot of different character types to split the string on?
The reason it's failing is because the split characters your using at
String[] dateAr = data_string.split("-|\||\(|\)|\s+");
are also in the month name.
put a debug point after that line, or do a for each over the dateAr array and log the results. That way, you can understand how it's being split.

Related

Regex: starts with messages and string between parent message curly brace

I want to get all the message data. Such that it should look for message and all the data between curly braces of the parent message. With the below pattern, I am not getting all parent body.
String data = "syntax = \"proto3\";\r\n" +
"package grpc;\r\n" +
"\r\n" +
"import \"envoyproxy/protoc-gen-validate/validate/validate.proto\";\r\n" +
"import \"google/api/annotations.proto\";\r\n" +
"import \"google/protobuf/wrappers.proto\";\r\n" +
"import \"protoc-gen-swagger/options/annotations.proto\";\r\n" +
"\r\n" +
"message Acc {\r\n" +
" message AccErr {\r\n" +
" enum Enum {\r\n" +
" UNKNOWN = 0;\r\n" +
" CASH = 1;\r\n" +
" }\r\n" +
" }\r\n" +
" string account_id = 1;\r\n" +
" string name = 3;\r\n" +
" string account_type = 4;\r\n" +
"}\r\n" +
"\r\n" +
"message Name {\r\n" +
" string firstname = 1;\r\n" +
" string lastname = 2;\r\n" +
"}";
List<String> allMessages = new ArrayList<>();
Pattern pattern = Pattern.compile("message[^\\}]*\\}");
Matcher matcher = pattern.matcher(data);
while (matcher.find()) {
String str = matcher.group();
allMessages.add(str);
System.out.println(str);
}
}
I am expecting response like below in my array list of string with size 2.
allMessage.get(0) should be:
message Acc {
message AccErr {
enum Enum {
UNKNOWN = 0;
CASH = 1;
}
}
string account_id = 1;
string name = 3;
string account_type = 4;
}
and allMessage.get(1) should be:
message Name {
string firstname = 1;
string lastname = 2;
}
First remove the input prior to "message" appearing at the start of the line, then split on newlines followed by "message" (include the newlines in the split so newlines that intervene parent messages are consumed):
String[] messages = data.replaceAll("(?sm)\\A.*?(?=message)", "").split("\\R+(?=message)");
See live demo.
If you actually need a List<String>, pass that result to Arrays.asList():
List<String> = Arrays.asList(data.replaceAll("(?sm)\\A.*?(?=message)", "").split("\\R+(?=message)"));
The first regex matches everything from start up to, but not including, the first line that starts with message, which is replaced with a blank (ie deleted). Breaking the down:
(?sm) turns on flags s, which makes dot also match newlines, and m, which makes ^ and $ match start and end of each line
\\A means the very start of input
.*? .* means any quantity of any character (including newline as per the s flag being set), but adding ? makes this reluctant, so it matches as few characters as possible while still matching
(?=^message) is a look ahead and means the following characters are a start of a line then "message"
See regex101 live demo for a thorough explanation.
The split regex matches one or more line break sequences when they are followed by "message":
\\R+ means one or more line break sequences (all OS variants)
(?=message) is a look ahead and means the following characters are "message"
See regex101 live demo for a thorough explanation.
Try this for your regex. It anchors on message being the start of a line, and uses a positive lookahead to find the next message or the end of messages.
Pattern.compile("(?s)\r\n(message.*?)(?=(\r\n)+message|$)")
// or
Pattern.compile("(?s)\r?\n(message.*?)(?=(\r?\n)+message|$)")
No spliting, parsing, or managing nested braces either :)
https://regex101.com/r/Wa2xxx/1

String index out of range: -5 [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I have a problem when i test runQuery, the problem is String index out of range: -5 and i can't find the solution
#Test
void testRunQuery() throws FileNotFoundException, IOException, InterruptedException {
final Answer answer = new Answer();
String[] args = new String[5];
final String year = "yyyy ";
final String month = "mm ";
final String day = "dd ";
final String limit = "limit ";
args[0] = year.substring(5);
args[1] = month.substring(3);
args[2] = day.substring(3);
args[3] = null;
args[4] = limit.substring(6);
Job result = answer.runQuery(args);
assertNotNull(result);
}
And this is runQuery where i make the query
public Job runQuery(final String[] args) throws InterruptedException {
// Use standard SQL syntax for queries.
// See: https://cloud.google.com/bigquery/sql-reference/
// Variabili per le query
final Integer yyyy=Integer.valueOf(args[ZERO].substring(FIVE)),
mm=Integer.valueOf(args[ONE].substring(THREE)),
dd=Integer.valueOf(args[TWO].substring(THREE)),
limit=Integer.valueOf(args[FOUR].substring(SIX));
final QueryJobConfiguration queryConfig = QueryJobConfiguration.newBuilder(
"SELECT DISTINCT owner_user_id "
+ "FROM `bigquery-public-data.stackoverflow.posts_answers` "
+ "WHERE extract(year from creation_date) = #yyyy "
+ "AND extract(month from creation_date) = #mm "
+ "AND extract(day from creation_date) = #dd "
+ "AND owner_user_id is not null "
+ "AND owner_user_id > 0 "
+ "ORDER BY owner_user_id ASC LIMIT #limit ")
.addNamedParameter("yyyy", QueryParameterValue.int64(yyyy))
.addNamedParameter("mm", QueryParameterValue.int64(mm))
.addNamedParameter("dd", QueryParameterValue.int64(dd))
.addNamedParameter("limit", QueryParameterValue.int64(limit))
.setUseLegacySql(false).build();
// Create a job ID so that we can safely retry.
final JobId jobId = JobId.of(UUID.randomUUID().toString());
Job queryJob=bigquery.create(JobInfo.newBuilder(queryConfig).setJobId(jobId).build());
// Wait for the query to complete.
queryJob = queryJob.waitFor();
// Check for errors
if (queryJob == null) {
throw new RuntimeException("Job no longer exists");
} else if (queryJob.getStatus().getError() != null) {
// You can also look at queryJob.getStatus().getExecutionErrors() for all
// errors, not just the latest one.
throw new RuntimeException(queryJob.getStatus().getError().toString());
}
return queryJob;
}
String index out of range: -5 at the line 93 of runQuery; this is the line:
final Integer yyyy=Integer.valueOf(args[ZERO].substring(FIVE))
You have misunderstood what argument Java's String.substring function takes.
In short, you appear to think the argument takes the length of the substring. It doesn't - rather, it specifies the "begin-index" - ie. where in the supplied string to start copying.
So when you say :
final String year = "yyyy ";
args[0] = year.substring(5);
you are NOT actually setting args[0] to a 5-character string. In stead, you are setting it to the part of string "yyyy " starting at position 5 - in other words, you are setting it to empty-string.
So when you subsequently say
final Integer yyyy=Integer.valueOf(args[ZERO].substring(FIVE)),
and assuming you have ZERO set to 0 and FIVE to 5, this will fail since you have args[0] as empty-string "", and you can't get a substring starting at position 5 from "".
To sum up, if you have
String myString = "smiles";
System.out.println("substring(0, 4) = <" + myString.substring(0, 4) + ">");
System.out.println("substring(2, 4) = <" + myString.substring(2, 4) + ">");
System.out.println("substring(4) = <" + myString.substring(4) + ">");
the output will be :
substring(0, 4) = <smil>
substring(2, 4) = <il>
substring(4) = <es>
In short, get rid of your ".substring" calls in both your test and your main code.
Check out the spec at https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int)
You first define a variable
final String year = "yyyy ";
then you use subString
args[0] = year.substring(5);
args[0] is now a String value of nothing( args[0] equals "")
then you are trying to subString it again.
final Integer yyyy=Integer.valueOf(args[ZERO].substring(FIVE)),
this won't work because args[0] is an empty String.
You should only use substring once, either inside the function or before calling the function.

Splitting array in string does not give last element

Hi I am splitting and storing string with use of array but does not give result
String str = "123456";
String[] arrOfStr = str.split("");
String otpnum1 = arrOfStr[0];
String otpnum2 = arrOfStr[1];
String otpnum3 = arrOfStr[2];
String otpnum4 = arrOfStr[3];
String otpnum5 = arrOfStr[4];
String otpnum6 = arrOfStr[5];
System.out.println("otp"+otpnum1+otpnum2+otpnum3+otpnum4+otpnum5+otpnum6);
OUTPUT
System.out: otp12345
You are printing without any space or newline, which is the reason you are not able to interpret individual variables. Use this
System.out.println("otp " + otpnum1+ " " + otpnum2+" " + " "+ otpnum3+ " " + otpnum4+ " " + otpnum5+ " " + otpnum6);
I understand, the output is 12345, and expected 123456 for the result.
But, looking your code looks like correct.
I have try your code here, for test, and works fine.
The output was: otp123456

String replace method is not working in android studio

I'm not too sure why my word doesn't get replaced in android studio.
private Calendar dateTime = Calendar.getInstance();
private SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy, EEE");
String dateFormat = dateFormatter.format(dateTime.getTime());
Button beginDate = (Button) findViewById(R.id.startDate);
beginDate.setText("From " + dateFormat);
// Other codes removed for simplicity
String beginD = beginDate.getText().toString().replace("From: ", "");
Log.d("Test", beginD);
Log result as follows:
06-16 14:14:01.957 23893-23893/packagename D/Testīš• From
16/06/2015, Tue
You're trying to replace "From: " but you only added "From " (without the :).
I don't see : in the input you entered, so From: won't be matched. I recommend using more generic pattern:
replaceAll("From:?\\s+", "");
Since replaceAll takes a regex, you can ask for optional :, followed by one or more space(s).
In your button text is no :. So you have to change the text of the botton to :
beginDate.setText("From: " + dateFormat);
or your regex to
String beginD = beginDate.getText().toString().replace("From ", "");

Best way to split a string containing question marks and equals

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.
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
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 ?
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(" ", ""));
}
}
}
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==p==?aname=?????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);
}

Categories