String index out of range: -5 [closed] - java

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.

Related

LDAP with Jacob-ADO-Wrapper

after a little bit of trying I managed to get results from the ldap-server at my company. Now I have a little problem and I seem to be too dump to find any documentation about it.
Command objCmd = new Command();
Recordset RS = new Recordset();
objCmd.setActiveConnection(conn);
objCmd.setCommandText("<LDAP://scdldap.siemens.net:389>;(&(objectClass=scdInternetPerson)(mail=" + email + "));" +searchKeyword+";subTree");
RS = objCmd.Execute();
if (RS.getBOF())
System.out.printf(email + ";" + "null" + "\n");
else {
RS.MoveFirst();
System.out.printf(email + ";" + RS.getFields().getItem(0).getValue() + "\n");
}
This works fine as long as I print the result out to the console. But I would need to get the value as a String (it is always a String), but I can't make it. Can somebody tell me what I am missing? I know this is some VariableType Error, because the result is of type Variant, but
Variant.toString() or anything else is not possible.
Try to convert Variant to Object and then to String, for example:
Variant From = new Variant(1);
Variant To = new Variant(6);
Object[] args = new Object[]{From, To};
String From1 = args[0].toString();
String To1 = args[1].toString();

NPE in a do/while loop due to EOF...catching the EOF earlier to avoid the NPE [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I have written this program to compare 2 files. They are 500mb to 2.8gb in size and are created every 6 hours. I have 2 files from 2 sources (NMD and XMP). They are broken up into lines of text that have fields separated by the pipe(|) character. Each line is a single record and may be up to 65,000 characters long. The data is about TV shows and movies, showing times and descriptive content. I have determined that any particular show or movie has a minimum of 3 pieces of data that will uniquely identify that show or movie. IE: CallSign, ProgramId and StartLong. The two sources for this data are systems called NMD and XMP hence that acronym added to various variables. So my goal is to compare a file created by NMD and one created by XMP and confirm that everything that NMD produces is also produced by XMP and that the data in each matched record is the same.
What I am trying to accomplish here is this: 1. Read the NMD file record by record for the 3 unique data fields. 2. Read the XMP file record by record and look for a match for the current record in the NMD file. 3.The NMD file should iterate one record at a time. Each NMD record should then be searched for in the entire XMD file, record by record for that same record. 4. Write a log entry in one of 2 files indicating success or failure and what that data was.
I have an NPE issue when I reach the end of the testdataXMP.txt file. I assume the same thing will happen for testdataNMD.txt. I'm trying to break out of the loop right after the readLine since the epgsRecordNMD or epgsRecordXMP will have just reached the end of the file if it at that point in the file. The original NPE was for trying to do a string split on null data at the end of the file. Now I'm getting an NPE here according to the debugger.
if (epgsRecordXMP.equals(null)) {
break;
}
Am I doing this wrong? If I'm really at the end of the file, the readLine ought to return null right?
I did it this way too, but to my limited experience they feel like they are effectively the same thing. It too threw an NPE.
if (epgsRecordXMP.equals(null)) break;
Here's the code...
public static void main(String[] args) throws java.io.IOException {
String epgsRecordNMD = null;
String epgsRecordXMP = null;
BufferedWriter logSuccessWriter = null;
BufferedWriter logFailureWriter = null;
BufferedReader readXMP = null;
BufferedReader readNMD = null;
int successCount = 0;
readNMD = new BufferedReader(new FileReader("d:testdataNMD.txt"));
readXMP = new BufferedReader(new FileReader("d:testdataXMP.txt"));
do {
epgsRecordNMD = readNMD.readLine();
if (epgsRecordNMD.equals(null)) {
break;
}
String[] epgsSplitNMD = epgsRecordNMD.split("\\|");
String epgsCallSignNMD = epgsSplitNMD[0];
String epgsProgramIdNMD = epgsSplitNMD[2];
String epgsStartLongNMD = epgsSplitNMD[9];
System.out.println("epgsCallsignNMD: " + epgsCallSignNMD + " epgsProgramIdNMD: " + epgsProgramIdNMD + " epgsStartLongNMD: " + epgsStartLongNMD );
do {
epgsRecordXMP = readXMP.readLine();
if (epgsRecordXMP.equals(null)) {
break;
}
String[] epgsSplitXMP = epgsRecordXMP.split("\\|");
String epgsCallSignXMP = epgsSplitXMP[0];
String epgsProgramIdXMP = epgsSplitXMP[2];
String epgsStartLongXMP = epgsSplitXMP[9];
System.out.println("epgsCallsignXMP: " + epgsCallSignXMP + " epgsProgramIdXMP: " + epgsProgramIdXMP + " epgsStartLongXMP: " + epgsStartLongXMP);
if (epgsCallSignXMP.equals(epgsCallSignNMD) && epgsProgramIdXMP.equals(epgsProgramIdNMD) && epgsStartLongXMP.equals(epgsStartLongNMD)) {
logSuccessWriter = new BufferedWriter (new FileWriter("d:success.log", true));
logSuccessWriter.write("NMD match found in XMP " + "epgsCallsignNMD: " + epgsCallSignNMD + " epgsProgramIdNMD: " + epgsProgramIdNMD + " epgsStartLongNMD: " + epgsStartLongNMD);
logSuccessWriter.write("\n");
successCount++;
logSuccessWriter.write("Successful matches: " + successCount);
logSuccessWriter.write("\n");
logSuccessWriter.close();
System.out.println ("Match found");
System.out.println ("Successful matches: " + successCount);
}
} while (epgsRecordXMP != null);
readXMP.close();
if (successCount == 0) {
logFailureWriter = new BufferedWriter (new FileWriter("d:failure.log", true));
logFailureWriter.write("NMD match not found in XMP" + "epgsCallsignNMD: " + epgsCallSignNMD + " epgsProgramIdNMD: " + epgsProgramIdNMD + " epgsStartLongNMD: " + epgsStartLongNMD);
logFailureWriter.write("\n");
logFailureWriter.close();
System.out.println ("Match NOT found");
}
} while (epgsRecordNMD != null);
readNMD.close();
}
}
You should not make this:
if (epgsRecordXMP.equals(null)) {
break;
}
If you want to know if epgsRecordXMPis null then the if should be like this:
if (epgsRecordXMP == null) {
break;
}
To sum up: your app throws NPE when try to call equals method in epgsRecordXMP.

Better string manipulation code

I'm looking for an efficient (one line) string manipulation code to achieve this, regex probably.
I have a string, for example, "Calvin" and I need to convert this to "/C/a/l/Calvin".
i.e. take first three characters, separate them using '/' and later append the original string.
This is the code I've come up with and its working fine, just looking for a better one.
String first = StringUtils.substring(prodName, 0, 1);
String second = StringUtils.substring(prodName, 1, 2);
String third = StringUtils.substring(prodName, 2, 3);
String prodPath = path + "/" + first + "/" + second + "/" + third + "/" + prodName + "/" ;
prodName.replaceAll("^(.)(.)(.).*", "/$1/$2/$3/$0")
What is the point of StringUtils.substring(prodName, 0, 1) when the built-in prodName.substring(0, 1) will do the same thing??
Anyway, assuming prodName is always at least 3 characters long (since you didn't give rules for expected output if it is not), this is the fastest way to do it:
String prodPath = path + '/' +
prodName.charAt(0) + '/' +
prodName.charAt(1) + '/' +
prodName.charAt(2) + '/' +
prodName + '/';
Normally, char + char is integer addition, not string concatenation, but since the first value is a String, and the + operator is left-associative, all + operators are string concatenations, not numeric additions.
How about using String.charAt
StringBuilder b = new StringBuilder (path);
b.append ('/').append (prodName.charAt (0))
.append ('/').append(prodName.charAt (1))
.append ('/').append(prodName.charAt (2))
.append ('/').append (prodName).append ('/');
Don't use regex for simple stuff like this. You may save a couple lines, but you loose a lot in readability. Regex usually take some time to understand when reading them.
String s = path;
for (int i = 0; i < 3; i++)
s += prodName.substring(i,i+1) + "/";
s += prodName
You can use MessageFormat.format()
MessageFormat.format("{0}/{1}/{2}/{3}/{4}/", baseDir, name.charAt(0), name.charAt(1), name.charAt(2), name);
imho i would wrap it for readability,
private String getProductionDirectoryPath(String baseDir, String name) {
return MessageFormat.format("{0}/{1}/{2}/{3}/{4}/", baseDir, name.charAt(0), name.charAt(1), name.charAt(2), name);
}
Positive look ahead can be used
public static void main(String[] args) {
String s = "Calvin";
System.out.println(s.replaceAll("(?=^(\\w)(\\w)(\\w))", "/$1/$2/$3/"));
}
O/P:
/C/a/l/Calvin
No use of a regex, but a simple split over nothing =)
String[] firstThree = prodName.split("");
String prodPath = path + "/" + firstThree[0] + "/" + firstThree[1] + "/" + firstThree[2] + "/" + prodName + "/";
Another approach is using charAt():
String prodPath = path + "/" + prodName.charAt(0) + "/" + prodName.charAt(1) + "/"+ prodName.charAt(2) + "/" + prodName + "/";
You said efficient but you maybe meant terse. I doubt either should be an objective, so you have a different problem.
Why do you care that this string transformation requires four lines of code? Are you concerned that something that in your mind is one operation ("create transformed string") is spread over four Java operations? You should extract the four lines of Java into their own method. Then, when you read the code where the operation is needed you have one conceptual operation ("create transformed string") corresponding to one Java operation (call a method). You could call the methid createTransformedString to make the code even clearer.
You can use String Builder:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++) {
sb.append("/").append(prodName.charAt(i));
}
sb.append('/').append(prodName);
Or you can put all the code in loop:
int size = 2;
StringBuilder sb = new StringBuilder();
for (int i = 0; i <= size; i++) {
if (i == 0)
sb.append('/');
sb.append(prodName.charAt(i)).append("/");
if (i == size)
sb.append(prodName);
}

Java empty String split ArrayIndexOutOfBoundsException [duplicate]

This question already has answers here:
Java String split is not working
(3 answers)
Closed 7 years ago.
I have come across an unexpected feature in the split function of String in Java, here is my code:
final String line = "####";
final String[] lineData = line.split("#");
System.out.println("data: " + lineData[0] + " -- " + lineData[1]);
This code gives me an ArrayIndexOutOfBoundsException, whereas I would expect it to print "" and "" (two empty Strings), or maybe null and null (two null Strings).
If I change my code for
final String line = " # # # #";
final String[] lineData = line.split("#");
System.out.println("data: " + lineData[0] + " -- " + lineData[1]);
Then it prints " " and " " (the expected behaviour).
How can I make my first code not throwing an exception, and giving me an array of empty Strings?
Thanks
You can use the limit attribute of split method to achieve this. Try
final String line = "####";
final String[] lineData = line.split("#", -1);
System.out.println("Array length : " + lineData.length);
System.out.println("data: " + lineData[0] + " -- " + lineData[1]);
As always, answer is written in the Javadoc
This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.
Since your array is composed only by empty strings, they are not added to it, thus trying to access the values result in an ArrayOutOfBoundException.
If I understand your question, this would do it -
final String line = " # ";
final String[] lineData = line.split("#");
System.out.println("data: " + lineData[0] + " -- " + lineData[1]);
The problem is that the empty string isn't a character.

Optimize String += or Concat? [duplicate]

This question already has answers here:
String concatenation: concat() vs "+" operator
(12 answers)
Closed 9 years ago.
I am writing a file with possibly 1000 data points. I have classes for all of these and am currently writing all of the data at the end (the datapoints are taken at 1s intervals). What I am currently doing is written below, and it's very slow. Would I be better off changing how I am writing the string/bytes to the file? Or would I be better off writing this information to some file pointer as the application is running?
Btw, all of the things such as getAccuracy() and such are floats/ints (so it has to convert those also).
fileStr = "";
fileStr += "timestamp,Accuracy,Altitude,Latitude,Longitude,GPSSatelliteEntries\r\n";
for (Iterator<Entry> i = entries.iterator(); i.hasNext(); ) {
Entry item = i.next();
long ts = item.getTs();
DataEntry d = item.getD();
List<GPSSatelliteEntry> satellites = item.getG();
// write stuff
fileStr += ts + ",";
fileStr += d.getAccuracy() + "," + d.getAltitude() + "," + d.getLatittude() + "," + d.getLongitude() + ",";
fileStr += "[";
boolean entered = false;
for (Iterator<GPSSatelliteEntry> j = satellites.iterator(); j.hasNext(); ) {
GPSSatelliteEntry item2 = j.next();
entered = true;
fileStr += "(" + item2.getAzimuth() + "," + item2.getElevation() + "," + item2.getPrn() + "," + item2.getSnr() + "),";
}
// chop off extra ,
if (entered)
fileStr = fileStr.substring(0, fileStr.length() - 1);
fileStr += "]";
fileStr += "\r\n";
}
Everytime you have hard work with Strings, use StringBuilder or StringBuffer to achieve better performance .
Don't forget that String is immutable, and each time you modify String new instance will be created and it costs performance.
Most probably string buffer
A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified.
or go for string builder
StringBuilder stuff = new StringBuilder();
stuff.append("PUT YOUR STRINGS HERE");
stuff.append("PUT YOUR STRINGS HERE");
Then you can use 'stuff' to print the strings.
Put it in a loop and iterate over a large number with a timer to see the advantages, it's pretty interesting.

Categories