0

I am trying to make a program that processes "large" text file. The textfile displays 1000 lines, each for one faculty staff member. Each line contains firstname, lastname, rank and salary.

Link to the textfile: http://cs.armstrong.edu/liang/data/Salary.txt

The program should count the amount of employees by rank, and the total salary for each group. At the end, the total salary for each group should be displayed, along with the average salary for an employee with a given rank. I have not finished the entire program, and I'm currently making sure that the textfile is read correctly.

Code example below:

package ch12;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

public class Chapter_12_E25_ProcessLargeDataSet {

    public static void main(String[] args) throws IOException {

        int assistantCount = 0;
        int associateCount = 0;
        int fullCount = 0;
        int facultyCount = 0;

        double assistantSalary = 0;
        double associateSalary = 0;
        double fullSalary = 0;
        double facultySalary = 0;

        try {
            URL url = new URL("http://cs.armstrong.edu/liang/data/Salary.txt");
            Scanner input = new Scanner(url.openStream());

            while (input.hasNext()) {

                String firstName = input.next();
                String lastName = input.next();
                String rank = input.next();
                double salary = input.nextDouble();

                if (rank.contains("assistant")) {
                    assistantCount++;
                    System.out.println("Rank is " + rank + " and salary is " + salary);

                } else if (rank.contains("associate")) {
                    associateCount++;
                    System.out.println("Rank is " + rank + " and salary is " + salary);
                } else {
                    fullCount++;
                    System.out.println("Rank is " + rank + " and salary is " + salary);
                }   
            }
            input.close();
        }
        catch (MalformedURLException ex) {
            ex.printStackTrace();
            System.exit(1);
        }
        catch (FileNotFoundException ex) {
            ex.printStackTrace();
            System.exit(2);
        }

    }

}

The line double salary = input.nextDouble() causes an InputMismatchException . If i change the variable salary to a String instead of a double, the salary is read correctly. If i change double salary = input.nextDouble() into double salary = Double.parseDouble(input.next()), I get the right double value. It doesen't bother me to use this approach, but I'm just curious why the scanner does not accept the salaries as a double value.

Can anyone please explain why?

Also, a sub question that is off-topic. If I change the filename Salary.txt in the argument for the URL object to a file that does not exists, FileNotFoundException in catch statement nr2 is not thrown, but instead an InputMismatchException is thrown. Why is the InputMismatchException thrown instead of FileNotFoundException?

Esben86
  • 483
  • 8
  • 21
  • What is your locale and what is the decimal separator? – Tunaki Jun 08 '16 at 11:45
  • I reside in Norway, but I haven't set any specific locale or decimal seperator. – Esben86 Jun 08 '16 at 11:52
  • Can you take a look at this question? http://stackoverflow.com/questions/17150627/scanner-double-value-inputmismatchexception – Tunaki Jun 08 '16 at 11:54
  • This might help http://stackoverflow.com/questions/17150627/scanner-double-value-inputmismatchexception – Aku Nour Jun 08 '16 at 11:57
  • Thanks for all inputs! I will finish the program using parseDouble(), and then have a look. – Esben86 Jun 08 '16 at 11:59
  • @Esben86 What you need to do, probably, is set a locale on your `Scanner` object, like the linked answers. This is what I was trying to go to with my first comment: `Scanner` by default uses your system locale, that may have a decimal separator different that the decimal separator in your file. – Tunaki Jun 08 '16 at 12:03
  • @Tunaki I did this and it works fine now. I guess my default decimal seperator is "," instead of "." . – Esben86 Jun 08 '16 at 12:41

3 Answers3

1

Most likely your scanner uses the wrong locale. Based on the values of your Salary.txt, you simply have to change your scanner's locale to english. Try this:

import java.util.Locale;
...
Scanner input = new Scanner(url.openStream());
input.useLocale(Locale.ENGLISH);
Lonkey
  • 183
  • 10
1

Also, a sub question that is off-topic. If I change the filename Salary.txt in the argument for the URL object to a file that does not exists, FileNotFoundException in catch statement nr2 is not thrown, but instead an InputMismatchException is thrown. Why is the InputMismatchException thrown instead of FileNotFoundException?

The server actuallay delivers a file (most likely 404) which doesn't match the expected format to open a stream on.

The line double salary = input.nextDouble() causes an InputMismatchException . If i change the variable salary to a String instead of a double, the salary is read correctly. If i change double salary = input.nextDouble() into double salary = Double.parseDouble(input.next()), I get the right double value. It doesen't bother me to use this approach, but I'm just curious why the scanner does not accept the salaries as a double value.

Your whole procedure is pretty fragile and will crash (or even worse: delvier wrong results) if the file format is not held correctly 100 percent. I would recommend to read the whole line and then split using a regular expression. Then check if all values are the expected type (e.g. double/String) and not null and proceed in adding them to your statistic. If the splitting fails/values are null/wrong you can add an error message to your output and skip the line to proceed.

carrybit
  • 161
  • 9
0

While I'm not familiar with scanner, a quick look at the api has found a variety of "hasNext(something)" methods. Such as...

hasNextInt()

hasNextFloat()

hasNextDouble()

hasNextLine()

Now you probably want the program to figure out what it should use next. If you setup the program correctly, I think you could simply test the next line with "hasNext(something)" for each possible type of value. When the hasNext(something) returns true, then get the value with the next(something). The concept in an example would be...

hasNextInt() returns false...

(skips nextInt() )

hasNextDouble() returns true...

nextDouble()

You're gonna need to take a look at https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html .

Tyler
  • 957
  • 11
  • 27