Getting ArrayIndexOutOfBound when using line.split on the string - java

Getting indexOutOfBound. After sucessfull file save. I open the file to perform the following tasks: find the total costPerItem, totalCount and sum. Don't know why I'm getting out of bound. Error points out to
totalCost =+ Double.parseDouble(index[1].trim());
Source code:
Scanner data = new Scanner(new File("registryCopy.txt"));
while(data.hasNext()){
String line = data.nextLine();
System.out.println(line);
String[] index = line.split("\\t");
totalCost += Double.parseDouble(index[1].trim());
totalCount += Integer.parseInt(index[2].trim());
sum = totalCost/totalCount;
}
Error
Error: "main" java.lang.ArrayIndexOutOfBoundsException: 1
which is: totalCost += Double.parseDouble(index[1].trim());
For some reasons it doesn't split the line. Text file is as follow:
item1 15.00 3
item2 15 2
item3 14 3
File was created before and promted the user to input that data. Source for that:
while(userInput.charAt(0)!='n'){
/**
* Need only one PrintWriter out0 i.e, then I either use the userbased name OR fixed name creation i.e registryCopy.txt(true will
* not overwrite the file but go to the next).
*/
PrintWriter out0 = new PrintWriter(new BufferedWriter(new FileWriter("registryCopy.txt", true)));
System.out.print("Enter item name: ");
itemName = kybd.next();//user String
out0.print(itemName + " ");
System.out.print("Enter item price: $");
price = kybd.next();
out0.print(price + " ");
System.out.print("Enter item quantity: ");
quantity = kybd.next();
out0.println(quantity);
System.out.print("Do you have another item to scan? Yes(y) or No(n): ");
userInput= kybd.next();
out0.flush();
}//end of whileLoop
Update1: You guys are awesome, \s did the trick. Beer on me when you're in Chicago. Thanks
OUTPUT sourceCode:
sum = totalCost*totalCount;
System.out.println("");
System.out.println(totalCost);
System.out.println(totalCount);
System.out.println(sum);
SOP:
item1 15.00 3
item2 15 2
item3 14 3
item5 10.00 3
item 5 12
bla 11 5
bread 1 15
item14 5 3
76.0
46
3496.0

Your call of split splits on tabs; it appears that your input has some other kind of whitespace separating the tokens.
To split on any kind of whitespace, use "\\s":
String[] index = line.split("\\s");
\s is a regular expression that stands for any of the following: ' ', '\t', '\n', '\x0B', '\f', '\r'.

Your program that writes the file puts space characters between the fields. Your program that reads the file is trying to split the lines on tab characters, instead of spaces. You have two choices.
Change the program that writes the file, so that it inserts tab characters - that is, wherever you have + " " in the source, change it to + "\t"
Change the program that reads the file, so that it splits the line on space characters. That is, make it line.split(" "). Alternatively, you can use line.split("\\s") which will split on any kind of white space.

Related

Reading from a CSV file parsing error/problem

Hello I am having issues reading from csv file which contains 3 columns per row. I cant seem to parse the last cell (3) to an integer even though it is always a "parsable" string:
Berlin,Buenos Aires,7402 I can't seem to get 7402 all the compiler throws is:
"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:658)
at java.base/java.lang.Integer.parseInt(Integer.java:776)
This is the code I have:
Scanner scan = new Scanner("worldcities.csv");
scan.useDelimiter("[,\\n]"); // get everything before a comma or a newline
while(scan.hasNext()) { // while this file has something then we
edge.v1 = scan.next(); // take vertice1 ----> city 1
edge.v2 = scan.next(); //take vertice2 ----> city 2
edge.e = Integer.parseInt(scan.next()); // parse the third value as int(distance between city1 and city2)
minheap.add(edge);
}
scan.close();
I seem to be able to get the first 2 values fine in the debugger.
the console just shows "
You can iterate throught file lines with the nextLine() method, as in this example:
Scanner scanner = new Scanner(new File("worldcities.csv"));
while (scanner.hasNextLine()) {
String columns[] = scanner.nextLine().split(",");
edge.v1 = columns[0]; // take vertice1 ----> city 1
edge.v2 = columns[1]; //take vertice2 ----> city 2
edge.e = Integer.parseInt(columns[2]); // parse the third value as int(distance between city1 and city2)
minheap.add(edge);
}
scanner.close();
or with using the Files class without the Scanner:
List<String> rows = Files.readAllLines(Paths.get("worldcities.csv"));
for (String row : rows) {
String columns[] = row.split(",");
edge.v1 = columns[0]; // take vertice1 ----> city 1
edge.v2 = columns[1]; //take vertice2 ----> city 2
edge.e = Integer.parseInt(columns[2]); // parse the third value as int(distance between city1 and city2)
minheap.add(edge);
}
Also you can use a special library for working with CVS files, for example look at Apache Commons CSV library.

Read multi line text file containing word and integer combinations, then calculate and display average

First time posting here, so please bear with me! I have a programming project due and I need help figuring out how to read through a text file (using a scanner) that contains multiple words and integers on a single line. The text file is a list of state names and their respective Average Family Incomes over a 3 year span. I need to get those values and calculate the average over the three years and display it all back in a nice table.
My problem is that I can get the average of the first few lines because they only have one word and three values. Using scanner.next() gets me past the first few lines, but there are multiple lines that contain 2 or more words and then the three values.
Currently, I get an InputMismatchException after the scanner reaches "District of Colombia" and it won't get the next value since scanner.next() only gets me to the word "of". Is there any way around this? Here is the first part of the project that just outputs all of the data (without an average):
Part 1 (works)
public class FamilyIncomeByState {
public void familyIncomeFile() throws IOException {
File income = new File ("src\\hw2p2\\FamilyIncome.txt");
Scanner scanner = new Scanner (income);
String year = scanner.nextLine();
System.out.println(year); System.out.println("--------------------------------------------");
while (scanner.hasNextLine()){
String line = scanner.nextLine();
System.out.println(line);
System.out.println(" ");
}
scanner.close();
}
}
Part 2 (doesn't work)
EDIT: Put in the wrong code the first time, this is the correct code.
public class AverageFamilyIncomeByState {
public void familyAverageIncomeFile() throws IOException {
File income = new File ("src\\hw2p2\\FamilyIncome.txt");
Scanner scanner = new Scanner (income);
String year = scanner.nextLine();
System.out.println(year + " Average");
System.out.println("-------------------------------------------------------");
while(scanner.hasNextLine()) {
String words = scanner.next();
double num1 = scanner.nextDouble();
double num2 = scanner.nextDouble();
double num3 = scanner.nextDouble();
double averageD = (num1 + num2 + num3) / 3;
BigDecimal average = BigDecimal.valueOf(averageD);
System.out.println(words + " " + average);
System.out.println(" ");
scanner.nextLine();
}
scanner.close();
}
}
And here is the content of the text file:
State 2002 2003 2004
Alabama 53754 54594 51451
Alaska 69868 71395 66874
Arizuna 56857 56067 55663
Arkansas 49551 47838 44537
California 65766 63761 63206
Colorado 68089 67634 66624
Connecticut 81891 82517 82702
Delaware 69469 73301 69360
District of Columbia 55692 61799 63406
Florida 57473 56824 55351
Georgia 60676 59497 59489
Hawaii 67564 66014 65872
Idaho 54279 51098 53722
Illinois 69168 66507 68117
Indiana 63022 63573 62079
Iowa 61238 61656 57921
Kanses 61926 61686 56784
Kentucky 54030 54319 51249
Louisiana 52299 51234 47363
Maine 58802 58425 56186
Maryland 77938 82879 77562
Massachusetts 78312 80247 78025
Michigan 67995 68337 68740
Minnesota 72379 72635 70553
Mississippi 47847 46810 46331
Missouri 59764 61036 61173
Montana 51791 48078 46142
Nebraska 60129 60626 57040
Nevada 59588 59283 59614
New Hampshire 72369 72606 71661
New Jersey 82406 80577 78560
New Mexico 48422 46596 47314
New York 65461 66498 64520
North Carolina 58227 56500 57203
North Dakta 57070 55138 53140
Ohio 63934 64282 62251
Oklahoma 51377 53949 48459
Oregon 60262 58737 58315
Pennsylvania 64310 66130 65411
Rhode Island 67646 70446 68418
South Carolina 56110 59212 56294
South Dakota 55359 59718 55150
Tennessee 55605 56052 54899
Texas 56278 56606 53513
Utah 59864 59035 57043
Vermont 62331 62938 59125
Virginia 66889 69616 68054
Warshington 66531 65997 63568
West Virginia 47550 49470 46270
Wisconsin 66988 65441 66725
Wyoming 57148 58541 55859
And here is my main method:
package hw2p2;
import java.io.IOException;
public class Launcher {
public static void main(String[] args) throws IOException {
FamilyIncomeByState familyIncomeByState = new FamilyIncomeByState();
familyIncomeByState.familyIncomeFile();
AverageFamilyIncomeByState familyAverageIncomeByState = new AverageFamilyIncomeByState();
familyAverageIncomeByState.familyAverageIncomeFile();
}
}
The part I'm stuck on should have an output that lists the Average values as a Fifth Column, but it just won't cycle past the 2nd word in a state name. Let me know if there's any more relevant information you need. Thanks!
This is just off the top of my head. But I think you should be able to use the split() function to split each line into strings separated by any white space. Then you can just take the last 3 strings in the array, converting each to an integer (or double) and then add those up. This way the number of words in the state is irrelevant.
int num1, num2, num3;
String[] tokens = scanner.nextLine().split("\\s+"); //split w/ delimeter
int length = tokens.length;
num 1 = Double.parseDouble(tokens[length - 1]); //last value of the array
num 2 = Double.parseDouble(tokens[length - 2]); //2nd last
num 3 = Double.parseDouble(tokens[length - 3]); //etc...
Hope this help! Let me know if you need any more clarification
sources:
whitespace delimeter:
How do I split a string with any whitespace chars as delimiters?
split function:
Splitting up data file in Java Scanner
By looking at the input format, I see that the columns are tab separated.
Use scanner.nextLine() to read the complete line, and then split the string on tab.
Hope it solves your issue
Since you said (in a comment) that the input file is tab separated you could use a StringTokenizer like this:
public void familyAverageIncomeFile() throws IOException {
File income = new File("src\\hw2p2\\FamilyIncome.txt");
Scanner scanner = new Scanner(income);
String year = scanner.nextLine();
System.out.println(year + " Average");
System.out.println("-------------------------------------------------------");
StringTokenizer tokenizer;
while(scanner.hasNextLine()) {
String words = scanner.nextLine();
tokenizer = new StringTokenizer(words, "\t");
String state = tokenizer.nextToken();
double num1 = Double.parseDouble(tokenizer.nextToken());
double num2 = Double.parseDouble(tokenizer.nextToken());
double num3 = Double.parseDouble(tokenizer.nextToken());
double averageD = (num1 + num2 + num3) / 3;
BigDecimal average = BigDecimal.valueOf(averageD);
System.out.println(words + "\t" + average);
System.out.println(" ");
}
scanner.close();
}
Output on my machine for the first few entries:
State 2002 2003 2004 Average
-------------------------------------------------------
Alabama 53754 54594 51451 53266.333333333336
Alaska 69868 71395 66874 69379.0
Arizuna 56857 56067 55663 56195.666666666664
Arkansas 49551 47838 44537 47308.666666666664
California 65766 63761 63206 64244.333333333336
Colorado 68089 67634 66624 67449.0
Connecticut 81891 82517 82702 82370.0
Delaware 69469 73301 69360 70710.0
District of Columbia 55692 61799 63406 60299.0
Hope this helps :) (Should work for the rest as well but a had to replace the tabs manually so I did only the first few and the one that caused your problem)

For-loop calculation of arbitrary times

I have a plain format txt file named enroll.txt which contains:
1997 2000
cs108 40 35
cs111 90 100
cs105 14 8
cs101 180 200
The first row shows the years of class
The second row first column shows the class name, and the following two columns show the number of students in the class in the years mentioned on the first row.
ex) In 1997, there were 40 students in class cs108.
My desired outcome: code prints as follows using
(i) split (ii) parseInt (iii) for-loop
student totals:
1997: 324
2000: 343
But this code should also work for any number of years (for example if I had student numbers for four years for each class instead of two, the code would still give me a similar output as below with student totals of say 1997, 2000, 2001, 2002 etc.)
What I have so far:
import java.util.*;
import java.io.*;
public class ProcessCourses{
public static void main(String[] args) throws FileNotFoundException{
Scanner console = new Scanner(System.in);
String fileName = console.nextLine();
Scanner input = new Scanner(new File(fileName));
while(input.hasNextLine()){
String line = input.nextLine();
String[] arr = line.split(" ");
//......????
}
}
}
What would go inside the //....????
So in the first line you have years, read them first :
Scanner input = new Scanner(new File(fileName));
String str = input.nextLine();
String[] years = str.split(" ");
Now you have set of student's information,
int[] total = new int[years.length];
while(input.hasNextLine()){
String line = input.nextLine();
String[] strength = line.split(" ");
int len = strength.length; // no of entries which includes course id + "years" no.of numbers.
for(int i=1;i<len;i++){ // from 1 because you don't care the course id
total[i-1] = total[i-1] + Integer.parseInt(strength[i]);
}
}
Then just print it :
for(int i=0;i<years.length;i++){
System.out.println(years[i]+ " : " + total[i]);
}

Manipulating Strings in a File Scanner ~ Java

I was given a file that has list of names phone numbers, calls in and out ect... Like this
Adams#Marilyn#8233331109#0#0#01012014#C
Anderson#John#5025559980#20#15#12152013#M
Baker-Brown#Angelica#9021329944#0#3#02112014#C
The # are delimiters between data items and each line has the call status as the last item.
I need to know how I can display each persons information on the screen in a format such as:
Name Phone Calls Out Calls In Last Call
Marilyn Adams (823) 333-1109 0 0 01-01-2104
John Anderson (502) 555-9980 20 15 12-15-2013
Angelica Baker-Brown (859) 254-1109 11 5 02-11-2014
I have to use substring method to extract the phone number and add parentheses/dashes ect...
So Far my code looks like this
Also I am in a beginners Java coding class....
import java.util.Scanner;
import java.io.*;
public class phonedata2_1 {
public static void main(String[] args) throws IOException {
String Phonefile, FirstName, LastName;
Scanner PhoneScan, fileScan;
System.out.println(" Name Phone Calls Out Calls In Last Call Status");
fileScan = new Scanner(new File("phonedata.txt"));
while (fileScan.hasNext()) {
Phonefile = fileScan.nextLine();
PhoneScan = new Scanner(Phonefile);
PhoneScan.useDelimiter("#");
System.out.println(PhoneScan.next() + " "
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next());
}
System.out.println("\nTotal outgoing calls for the period: " + "\nTotal incoming calls for the period: \n");
}
}
Finds every "data-segment" by using regex, then splits it with # as delimiter and prints it:
File blub = new File("blub.txt");
Scanner scanner = null;
try
{
scanner = new Scanner(blub);
}
catch (FileNotFoundException e){}
while(scanner.hasNext("((\\S*)#){6}(\\w)"))
{
String buffer = scanner.next("((\\S*)#){6}(\\w)");
for(String value : buffer.split("#"))
System.out.print(value + " ");
System.out.println();
}
Output:
Adams Marilyn 8233331109 0 0 01012014 C
Anderson John 5025559980 20 15 12152013 M
Baker-Brown Angelica 9021329944 0 3 02112014 C
Note:
You can use any whitespace character to separate each data-segment in the input file, so even spaces are okay or tabs(or crazy mix with empty lines and so on).
For farther use of data:
you could add your data in an arraylist since buffer.split("#") gives you an array of the data-segment, so you can output it easier with your desired changes to each value.(or in a different order)
You can use the .split(String regex) to split the line you are reading by throwing in the # as a delimeter. This will yield an array which you can traverse and print the contents accordingly. Also, it would seem that besides the initial line, all call data starts with a , so you could use split twice to parse your text file:
EDIT: Seeing your comment, I also realized that afterwards, however, since the .split() method takes a regex as parameter, it means that this problem can be walked around without much hassle. My example is as follows:
String str = "Adams#Marilyn#8233331109#0#0#01012014#C Anderson#John#5025559980#20#15#12152013#M Baker-Brown#Angelica#9021329944#0#3#02112014#C";
String[] lines = str.split(" ");
System.out.println("Name\tPhone\tCalls\tOut\tCalls In\tLast Call");
for(String line : lines)
{
String[] lineInfo = line.split("#");
for(String info : lineInfo)
{
System.out.print(info + "\t");
}
System.out.println();
}
I had to add some extra tabs manually, but this is the output:
Name Phone Calls Out Calls In Last Call
Adams Marilyn 8233331109 0 0 01012014 C
Anderson John 5025559980 20 15 12152013 M
Baker-Brown Angelica 9021329944 0 3 02112014 C
Something like this should work. You still need to do all the manipulation of the phone number yourself, but all the data will be in the call info so you should be able to work from that!
while (fileScan.hasNext())
{
//Get a single record
Phonefile = fileScan.nextLine();
//Seperate the elements of the record
String[] callInfo = Phonefile.split("#");
for(String infoPart: callInfo)
{
System.out.print(infoPart+ "\t");
}
System.out.println()
}

Java split() method won't work a second time

The method updateEmployees(PersonnelManager pm) reads a text file and depending on the first character of each line (there are 3 possiblities) on the file, it executes different code. The PersonnelManager and Employee classes have no play in the problem, that's why I'm not including them here. Here is a sample input file:
n Mezalira, Lucas h 40000
r 5
d Kinsey
n Pryce, Lane s 50
r 4
Here is the method:
(the File and Scanner objects are declared out of the method)
public static boolean updateEmployees(PersonnelManager pm) {
try
{
file = new File(updates);
in = new Scanner(file);
}
catch (FileNotFoundException e)
{
System.out.println("Could not load update file.");
return false;
}
int currentLine = 1; //Keep track of current line being read for error reporting purpose
while (in.hasNext()) {
String line = in.nextLine();
//Check the type of update the line executes
//Update: Add new Employee
if (line.charAt(0) == 'n') {
String[] words = line.split("\\s"); //Split line into words. Index [0]: update type. [1]: last name. [2]: first name. [3]: employee type. [4]: wage.
words[1] = words[1].substring(0, words[1].length() - 1); //remove comma from last name
if (words.length != 5) { //If there are not 5 words or tokens in the line, input is incorrect.
System.out.println("Could not update. File contains incorrect input at line: " + currentLine);
return false;
}
if (words[3].equals("s")) //if employee is type SalariedEmployee
pm.addEmployee(new SalariedEmployee(words[2], words[1], Double.parseDouble(words[4])));
else if (words[3].equals("h")) //if employee is type HourlyEmployee
pm.addEmployee(new HourlyEmployee(words[2], words[1], Double.parseDouble(words[4])));
else {
System.out.println("Could not update. File contains incorrect input at line: " + currentLine);
return false;
}
//Display information on the console
System.out.println("New Employee added: " + words[1] + ", " + words[2]);
}
//Update: Raise rate of pay
if (line.charAt(0) == 'r') {
String[] words = line.split("\\s"); //Split line into words. Index [0]: update type. [1]: rate of wage raise
if (Double.parseDouble(words[1]) > 100.0) { //If update value is greater than 100
System.out.println("Error in line:" + currentLine + ". Wage raise rate invalid.");
return false;
}
for (int i =0; i<pm.howMany(); i++) { //Call raiseWages() method for all employees handled by the pm PersonnelManager
pm.getEmployee(i).raiseWages(Double.parseDouble(words[1]));
}
//Display information on the console
System.out.println("New Wages:");
pm.displayEmployees();
}
//Update: Dismissal of Employee
if (line.charAt(0) == 'd') {
String[] words = line.split("\\s"); //Split line into words. Index [0]: update type. [1]: last name of employee
if (words.length != 2) { //If there are not 2 words or tokens in the line, input is incorrect.
System.out.println("Could not update. File contains incorrect input at line: " + currentLine);
return false;
}
String fullName = pm.getEmployee(words[1]).getName(); //Get complete name of Employee from last name
pm.removeEmployee(words[1]);
//Display information on the console
System.out.println("Deleted Employee: " + fullName);
}
currentLine++;
}
return true;
}
Since there are 5 lines in the input file, the while loop should execute 5 times, but that's not what happens. when it reaches the 4th line in the input file: "n Pryce, Lane s 50", I get an "java.lang.StringIndexOutOfBoundsException" error, in line 25 of the code.
The problem occurs at lines 24 and 25:
String[] words = line.split("\\s"); //Split line into words. Index [0]: update type. [1]: last name. [2]: first name. [3]: employee type. [4]: wage.
words[1] = words[1].substring(0, words[1].length() - 1); //remove comma from last name
For the 4th line of input, the "line" String is not split in 5 Strings as it should. It is only split into one, which is in words[0] and it equals "n".
What I don't understand is the program used the same line of code to split the String for the first 3 lines of input, why doesn't it work on the 4th line?
When I change the input file to
n Mezalira, Lucas h 40000
r 5
d Kinsey
removing a second occurrence of the command "n", it works. In fact, every time I use an input file that uses the same command ("n", "r" or "d") more than once, the line where the command happens the second time will only be split into 1 string. containing the first token ( int this case "n", "r", or "d") on the line.
I hope I was clear in my explanation. If anyone know why this happens, please help.
Your split() call should really be split("\\s+") to allow for multiple blanks between fields.

Categories