IndexOf(), String index out of bounds: -1 - java

I have no idea what is happening. I have a list of products along with a number separated with a tab. When I use indexOf() to find the tab, I get a String index out of bounds error, and it says the index is -1. Here's the code:
package taxes;
import java.util.*;
import java.io.*;
public class Taxes {
public static void main(String[] args) throws IOException {
//File aFile = new File("H:\\java\\PrimeNumbers\\build\\classes\\primenumbers\\priceList.txt");
File aFile = new File("C:\\Users\\Tim\\Documents\\NetBeansProjects\\Taxes\\src\\taxes\\priceList.txt");
priceChange(aFile);
}
static void priceChange(File inFile) throws IOException {
Scanner scan = new Scanner("priceList.txt");
char tab = '\t';
while (scan.hasNextLine()) {
String line = scan.nextLine();
int a = line.indexOf(tab);
String productName = line.substring(0,a);
String priceTag = line.substring(a);
}
}
}
And here's the input:
Plyer set 10
Jaw Locking Plyers 10
Cable Cutter 7
16 oz. Hammer 5
64 oz. Dead Blow Hammer 12
Sledge Hammer 20
Cordless Drill 22
Hex Impact Driver 50
Drill Bit Set 30
Miter Saw 200
Circular Saw 40

Scanner scan = new Scanner("priceList.txt");
This line of code is wrong. This Scanner instance will scan the String "priceList.txt". It doesn't contain a tab, therefore indexOf returns -1.
Change it to:
Scanner scan = new Scanner(inFile);
to use the method argument, that is the desired file instance of your priceList.txt.

String.indexOf(char) will return -1 if an instance isn't found.
You need to check before proceeding that a isn't negative.
You can read more about the indexOf method here and here.

Because you are checking int a = line.indexOf(tab) in every iteration of the while loop, there has to be a tab in every single line of your document in order for the error to be prevented.
When your while (scan.hasNextLine()) loop runs into a line with no tab in it, the index is going to be -1, and you get the StringIndexOutOfBoundsException when trying to get line.substring(0,a), with a being -1.

while (scan.hasNextLine()) {
String line = scan.nextLine();
int a = line.indexOf(tab);
if(a!=-1) {
String productName = line.substring(0,a);
String priceTag = line.substring(a);
}
}

If you look very carefully at the input lines you have posted, you'll see
Jaw Locking Plyers 10
...
Cordless Drill 22
Hex Impact Driver 50
Drill Bit Set 30
that the "Hex Impact Driver" line has the price two characters to the right of the one in the lines before and after. This is an indication that "50" does not start at a tab position whereas "10" is at such a position, the next after the one for "22" and "30".
The Q&A editor does preserve TABs, so your editor preserves them as well, and your program should be able to recognize a TAB in the input lines.
That said, a TAB entered by hand (!) is a very poor choice for a separator. As you have experienced, text file presentation doesn't show it. It would be much better to use a special character that does not occur in the product names. Plausible choices are '|', '#', and '\'.
Another good way would be to use pattern matching to find the numeric price at the end of a line - the product name is what remains after removing the price and calling trim() on the remaining string.

Since it has been verified that indexOf(tab) returns -1, the question is why does the line of text not contain t a tab when you seem certain that it does?
The answer is most likely the settings on your IDE. For instance, I usually configure Netbeans to convert a tab to three spaces. So if you typed this input file yourself within an IDE, the tab-to-space conversion is likely the problem.
Work around:
If we copy/paste some text into Netbeans that includes tabs, the tabs do not get converted to spaces.
The text file could be created with notepad or any other simple text editor to avoid the problem.
Change the settings on your IDE, at least for this project.

Related

How do you go through ArrayList and find what is in the ArrayList using Scanner?

I am making an ArrayList of cars and I am having trouble how to iterate through the ArrayList and print what I ask using a scanner.
Example: I am looking for an Audi in the list, I want it to look through the ArrayList and if it is in the ArrayList print "We have a %s."
This is what I have so far:
public class Main {
public static void main(String[] args) {
ArrayList<String> car = new ArrayList<>();
car.add("Audi");
car.add("Chevrolet");
car.add("Dodge");
car.add("Ford");
car.add("Honda");
car.add("Toyota");
car.add("Volkswagen");
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
for(String name: car)
{
if(name == sc){
System.out.printf("We have a %s.", sc);
}
}
}
}
I think that real problem here1 is that you don't have a clear understanding of what a Scanner does.
A Scanner reads characters from a stream (for example System.in) and turns them into various kinds of values; e.g. integers, floating point numbers, strings and so on. The basic model is:
call hasNextXXX to test if there is a XXX to read.
call nextXXX to read a XXX.
So you are trying to get a name of a car manufacturer from the Scanner. Assuming that car manufacturer names don't have spaces in them, what you are reading is a white-space delimited token. The method for reading a token is Scanner::next. It returns the token as a String with any leading or trailing whitespace removed.
Aside: String::nextLine would also work, except that it returns the complete line with all white space entered by the user before or after the name2. If the user enters (for example) Ford with a space after it, then that won't match the value in your car list. To deal with that, you would need to do something like this:
String str = sc.nextLine().trim(); // 'trim' removes leading and
// trailing whitespace; e.g. SP,
// TAB, CR and NL characters.
Once you have the name as a String, you should String::equals to compare it against other strings. Comparing strings using == is incorrect in nearly all circumstances; see How do I compare strings in Java?
For a deeper understanding of Scanner, I recommend that you take the time to read the javadocs.
Your code doesn't do the above. Instead, it reads a line (i.e. str = sc.nextLine()) and doesn't use it. Then it uses == to test if the Scanner is equal to each String in your list. That fails, because a Scanner is not a String.
Aside: in Java, == for a reference type (i.e. for objects) means "is this the same object".
1 - The other possibility is that you didn't read the code that you had written carefully enough.
2 - ... apart from the line separator sequence; i.e. CR, NL or CR + NL. This is removed automatically by nextLine: refer to the javadocs for more details.

In Java, how do I read both Strings and Doubles from the same txt file? [duplicate]

I am creating a simple program to data read from a text file. The file stores information about a person, with the name, age and a number on each line:
Eg: File format per line
Francis Bacon 50 2
I can read in a file no problem if it is just text, but I am confused on how to differentiate between text and numbers. Here is a look at my code:
import java.io.*;
public class Test{
private People people[] = new People[5];
public Test(){
BufferedReader input;
input = new BufferedReader(new FileReader("People.txt"));// file to be readfrom
String fileLine;
int i = 0;
while (test != null){
fileLine = input.readLine();
// Confused as to how to parse this line into seperate parts and store in object:
// eg:
people[i].addName(fileLine - part 1);
people[i].addBookNo(fileLine - part 2);
people[i].addRating(fileLine - part 3)
i++
}
}
}
I strongly suggest you use the Scanner class instead. That class provides you with methods such as nextInt and so on.
You could use it to read from the file directly like this:
Scanner s = new Scanner(new File("People.txt"));
while (s.hasNext()) {
people[i].addName(s.next());
people[i].addBookNo(s.nextInt());
people[i].addRating(s.nextInt());
}
(Just realized that you may have spaces in the name. That complicates things slightly, but I would still consider using a scanner.)
An alternative solution would be to use a regular expression and groups to parse the parts. Something like this should do:
(.*?)\s+(\d+)\s+(\d+)
The following regex works on these 3 cases, breaking them into 3 matched groups.
Regex
(.*)\s+(\d+)\s+(\d+)
Cases
Francis Bacon 50 2
Jill St. John 20 20
St. Francis Xavier III 3 3
If you want to do in this way, you can try doing like this :
Fixing the way data will be present in the file, say
firstName.lastName.age.number;
Then you can write code to read data upto . and store it in a variable (you will be knowing what it is meant for) and after ";" there will be second entry.

Java Scanner get number from string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
The string is, for example "r1" and I need the 1 in an int form
Scanner sc = new Scanner("r1");
int result = sc.nextInt(); // should be 1
compiles correctly but has a runtime error, should I be using the delimiter? Im unsure what the delimiter does.
Well, there's a few options. Since you literally want to skip the "r" then read the number, you could use Scanner#skip. For example, to skip all non-digits then read the number:
Scanner sc = new Scanner("r1");
sc.skip("[^0-9]*");
int n = sc.nextInt();
That will also work if there are no leading non-digits.
Another option is to use non-digits as delimiters, as you mentioned. For example:
Scanner sc = new Scanner("x1 r2kk3 4 x56y 7g");
sc.useDelimiter("[^0-9]+"); // note we use + not *
while (sc.hasNextInt())
System.out.println(sc.nextInt());
Outputs the six numbers: 1, 2, 3, 4, 56, 7.
And yet another option, depending on the nature of your input, is to pre-process the string by replacing all non-digits with whitespace ahead of time, then using a scanner in its default configuration, e.g.:
String input = "r1";
input = input.replaceAll("[^0-9]+", " ");
And, of course, you could always just pre-process the string to remove the first character if you know it's in that form, then use the scanner (or just Integer#parseInt):
String input = "r1";
input = input.substring(1);
What you do depends on what's most appropriate for your input. Replace "non-digit" with whatever it is exactly that you want to skip.
By the way I believe a light scolding is in order for this:
Im unsure what the delimiter does.
The documentation for Scanner explains this quite clearly in the intro text, and even shows an example.
Additionally, the definition of the word "delimiter" itself is readily available.
There are some fundamental mistakes here.
First, you say:
One = sc.nextInt("r1");
compiles correctly ...
No it doesn't. If sc is really a java.util.Scanner, then there is no Scanner.nextInt(String) method, so that cannot compile.
The second problem is that the hasNextXXX and nextXXX methods do not parse their arguments. They parse the characters in the scanner's input source.
The third problem is that Scanner doesn't provide a single method that does what you are (apparently) trying to do.
If you have a String s that contains the value "r1", then you don't need a Scanner at all. What you need to do us something like this:
String s = ...
int i = Integer.parseInt(s.substring(1));
or maybe something this:
Matcher m = Pattern.compile("r(\\d+)").matcher(s);
if (m.matches()) {
int i = Integer.parseInt(m.group(1));
}
... which checks that the field is in the expected format before extracting the number.
On the other hand if you are really trying to read the string from a scanner them, you could do something like this:
String s = sc.next();
and then extract the number as above.
If the formatting is the same for all your input where the last char is the value you could use this:
String s = sc.nextLine()
Int i = Integer.parseInt(s.charAt(s.length() -1));
Else you could for instance make the string a char Array, iterate trough it and check whether each char is a number.

Ignore characters in between quote

I have several strings like this from a file, my code tells it to split each line by a comma and if a line is author, output it, if it is title output it, e.t.c. As labelled, no 2 prints out the output but no 1 prints out only title and journal, i basically think its because of the characters in between, here is my code that splits, how do i tell it to ignore the characters in between or replace them.
1. #Article{Balogh:2015:OBW,
author = "J{\'a}nos Balogh and J{\'o}zsef B{\'e}k{\'e}si and
Gy{\"o}rgy D{\'o}sa and Leah Epstein and Hans Kellerer
and Asaf Levin and Zsolt Tuza",
title = "Offline black and white bin packing",
journal = {Theor. Comput. Sci.}
}
2.#Article{DAngelo:2015:MSP,
author = "Gianlorenzo D'Angelo and Daniele Diodati and Alfredo
Navarra and Cristina M. Pinotti",
title = "The minimum $k$-storage problem on directed graphs",
journal = {Theor. Comput. Sci.}
}
Code that splits.
printArray = InArray[i].trim().split( ",(?=([^\"]*\"[^\"]*\")*(?![^\"]*\"))" ,-1);
i have tried this
printArray = InArray[i].trim().split(",");
this
//InArray[i]=InArray[i].replaceAll("[{}]","").replaceAll("[\\\"]", "");
printArray = InArray[i].trim().split( ",(?=([^\"]*\"[^\"]*\")*(?![^\"]*\"))" ,-1);
but i keep getting index out of bound exception
I basically did this to fix this.
printArray = InArray[i].replaceAll("\\\\\"", "").trim().split(",(?=([^\"]*\"[^\"]*\")*(?![^\"]*\"))

Novice programmer needs advice: "String index out of range" - Java

I'm pretty new to programming and I'm getting a error which I'm sure is a easy fix for more experienced people.
Here is what I have:
import java.io.*;
import java.util.Scanner;
public class ReadNamesFile
{
public static void main(String[] args) throws IOException {
// make the names.csv comma-separated-values file available for reading
FileReader f = new FileReader("names.csv");
BufferedReader r = new BufferedReader(f);
//
String lastName="unknown", firstName="unknown", office="unknown";
// get first line
String line = r.readLine();
// process lines until end-of-file occurs
while ( line != null )
{
// get the last name on the line
//
// position of first comma
int positionOfComma = line.indexOf(",");
// extract the last name as a substring
lastName = line.substring(0,positionOfComma);
// truncate the line removing the name and comma
line = line.substring(positionOfComma+1);
// extract the first name as a substring
firstName = line.substring(0,positionOfComma);
// truncate the line removing the name and comma
line = line.substring(positionOfComma+1);
// extract the office number as a substring
office = line.substring(0,positionOfComma);
// truncate the line removing the name and comma
line = line.substring(positionOfComma+2);
//
//
//
// display the information about each person
System.out.print("\nlast name = "+lastName);
System.out.print("\t first name = "+firstName);
System.out.print("\t office = "+office);
System.out.println();
//
// get the next line
line = r.readLine();
}
}
}
Basically, it finds the last name, first name and office number in a .csv file and prints them out.
When I compile I don't get any errors but when I run it I get:
java.lang.StringIndexOutOfBoundsException: String index out of range: 7
at java.lang.String.substring(String.java:1955)
at ReadNamesFile.main(ReadNamesFile.java:34)
Before trying to do the office number part, the first two (last and first name) printed out fine but the office number doesn't seem to work.
Any ideas?
Edit: Thanks for all the posts guys, I still can't really figure it out though. Can someone post something really dumbed down? I've been trying to fix this for an hour now and I can't get it.
Let's work by example, what issues you have with your code.
Eg: line: Overflow,stack
{ length: 14 }
Taking your program statements line by line -
int positionOfComma = line.indexOf(","); // returns 9
lastName = line.substring(0,positionOfComma); // should be actually postionOfComma-1
Now lastName has Overflow. positionOfComma has 9.
line = line.substring(positionOfComma+1);
Now line has stack.
firstName = line.substring(0,positionOfComma);
Asking substring from 0 to 9. But stack is only of length 5. This will cause String index out of range exeception. Hope you understood where you are doing wrong.
From JavaDoc:
(StringIndexOutOfBoundsException) - Thrown by String methods to
indicate that an index is either negative or greater than the size of
the string.
In your case, one of your calls to .substring is being given a value that is >= the length of the string. If line #34 is a comment, then it's the line above #34.
You need to:
a) Make sure you handle the case if you DON'T find a comma (i.e. if you cannot find and extract a lastName and/or firstName string)
b) Make sure the value of "positionOfComma + N" never exceeds the length of the string.
A couple of "if" blocks and/or "continue" statements will do the trick nicely ;-)
You correctly find positionOfComma, but then that logic applies to the original value of line. When you remove the last name and comma, positionOfComma is no longer correct as it applies to the old value of line.
int positionOfComma = line.indexOf(",");
this line of code might not find a comma and then positionOfComma will be -1. Next you substring something with (0,-1) - eeek no wonder it gives StringIndexOutOfBoundsException. Use something like:
int positionOfComma = 0;
if(line.indexOf(",")!=-1)
{
positionOfComma = line.indexOf(",");
}
You do have to do lots of checking of things sometimes especially when the data is whacked :(
http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#indexOf(java.lang.String)
PS I'm sure someone clever can make my coding look shabby but you get the point I hope :)

Categories

Resources