0

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!

Faraz
  • 6,025
  • 5
  • 31
  • 88
Iyrdin93
  • 3
  • 3
  • Are the values tab separated? That would make it much easier – scsere Feb 07 '16 at 01:16
  • @scsere Yes they are tab separated, I am however having trouble putting the values into an array by splitting. – Iyrdin93 Feb 07 '16 at 01:22
  • Do you need to put them into an array for later processing or is your only goal to calculate the average? – scsere Feb 07 '16 at 01:24
  • I only need to calculate the average and then display it along with the rest of the data for that line, and then move on to the next line. – Iyrdin93 Feb 07 '16 at 01:25
  • Okay. And is there always only one tab between the columns? or are the more between the first and the second one? – scsere Feb 07 '16 at 01:27
  • There are multiple between the first and second, but the others are only separated by one tab. – Iyrdin93 Feb 07 '16 at 01:29
  • @lyrdin93, i will give u a hint. read the whole line and store it in a string. Then seperate out numbers from string (yes google it). And then calculate the avgs of numbers – Faraz Feb 07 '16 at 01:31

3 Answers3

0

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

Prasad
  • 1
  • 1
0

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

Community
  • 1
  • 1
Z. Hertig
  • 16
  • 1
0

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)

scsere
  • 621
  • 2
  • 15
  • 25
  • @Iyrdin93 Okay nice, haven't seen that one until I posted mine, but this one should work even if there are multiple tabs (but no values) between the columns and you can easily expand for more columns by just adding additional ``tokenizer.nextToken()` (: – scsere Feb 07 '16 at 01:55
  • This worked very well! After reading the instructions our instructor gave us, I ended up using ZHertig's method exclusively since it more closely relates to our inclass learnings, but I will be sure to keep this method in mind for next time! Thanks again for your help! – Iyrdin93 Feb 07 '16 at 02:40