0

My assignment is:

  • Create a file that has 2 columns of numbers: Distance and Speed.
  • Write a class TravelInfo which has three pieces of information: Speed, Time, Distance.
  • The class should also have a method calcTime() which calculates the time it will take to reach a destination based on the distance and speed (recall: Time = Distance/Speed)
  • Write a main program that:
    • Creates an ArrayList of TravelInfo objects of size 10.
    • Prompts the user for the name of the file and reads the data into TravelInfo objects
    • Calls the calcTime() method on each TravelInfo object.
    • Creates an output file with the data written in the format: Distance, Time, Speed

Every time I run my program I get an error

Exception in thread "main" java.util.NoSuchElementException

Other than this error I think I have done everything right except maybe calling my method, and I still haven't formatted the output file yet (not quite sure how). I can't continue while I get this error.

Here is my main() method:

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

    Scanner keyboard = new Scanner(System.in);
    ArrayList<TravelInfo> list = new ArrayList<>();

    System.out.println("What is the name of the file?");
    String filename = keyboard.nextLine();
    File f = new File(filename);
    Scanner inputFile = new Scanner(f);
    while(inputFile.hasNext()) {
        int s = inputFile.nextInt();
        int d = inputFile.nextInt();
        int t = inputFile.nextInt();


        TravelInfo p = new TravelInfo(s, d, t);
        list.add(p);
        TravelInfo cls = new TravelInfo(s,d,t);
        cls.calcTime(t);
        cls.calcTime(s);
        cls.calcTime(d);

       // System.out.println("Time is " + cls.calcTime(t));

       /*for(int i=0; i<list.size(); i++) {
           list.get(i).print();
      */ }
        for(TravelInfo k : list)
            System.out.println(k);

        PrintWriter outputFile = new PrintWriter("Data.txt");
        outputFile.println(list);
        //outputFile.println();
        outputFile.close();
    }

}

And my TravelInfo class

public class TravelInfo {
    private int speed;
    private int distance;
    private int time;

    public TravelInfo(int s, int d, int t) {
        speed = s;
        distance = d;
        time = t;
    }
    public int calcTime(int time) {
        time = distance/speed;
        return time;
    }
}
skomisa
  • 16,436
  • 7
  • 61
  • 102
Nitro
  • 87
  • 7
  • Which scanner throws the exception? I assume it's the file one – Benjamin Urquhart May 02 '19 at 16:06
  • I think both but i'm not really sure – Nitro May 02 '19 at 16:07
  • It's gotta be one or the other. Can we see the full stack trace? – Benjamin Urquhart May 02 '19 at 16:08
  • Sorry what's a full stack trace? I'm new to programming so i'm not sure what that is – Nitro May 02 '19 at 16:10
  • [Here](https://stackoverflow.com/questions/3988788/what-is-a-stack-trace-and-how-can-i-use-it-to-debug-my-application-errors) – Benjamin Urquhart May 02 '19 at 16:11
  • Most likely, the file you're trying to parse is in a wrong format - input is exhausted. – Dorian Gray May 02 '19 at 16:11
  • Exception in thread "main" java.util.NoSuchElementException at java.util.Scanner.throwFor(Scanner.java:862) at java.util.Scanner.next(Scanner.java:1485) at java.util.Scanner.nextInt(Scanner.java:2117) at java.util.Scanner.nextInt(Scanner.java:2076) at cw7_3.CW7_3.main(CW7_3.java:31) C:\Users\bambo\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1 BUILD FAILED (total time: 2 seconds) – Nitro May 02 '19 at 16:11
  • You ran out of file to read – Benjamin Urquhart May 02 '19 at 16:15
  • What does that mean exactly? My file is a.txt file called numbers and in it I just have two rows of 5 numbers – Nitro May 02 '19 at 16:18
  • 1
    Five numbers? You're reading three numbers on each iteration. Five isn't divideable by three. – Dorian Gray May 02 '19 at 16:22
  • oh okay, i changed it to 6 and it ran properly and created the data file with my output but for some reason this was what was printed: cw7_3.TravelInfo@42a57993 cw7_3.TravelInfo@75b84c92 cw7_3.TravelInfo@6bc7c054 cw7_3.TravelInfo@232204a1 – Nitro May 02 '19 at 16:25
  • Well, what did you expect? In ´System.out.println(k)´, Java uses the default output for Objects. You mught want to override the `TravelInfo.toString()` method. – Dorian Gray May 02 '19 at 16:27
  • How would I go about doing that? – Nitro May 03 '19 at 02:01

2 Answers2

0

You shall do some more validation, and never use the nextXXX() methods blindly - something like

while(true)
{
    if (!inputFile.hasNextInt()) {
       System.err.println("Reading file failed - invalid format (s)");
       break;
    }
    int s = inputFile.nextInt();
    System.out.println("Reading s = " + s);

    if (!inputFile.hasNextInt()) {
       System.err.println("Reading file failed - invalid format (d)");
       break;
    }
    int d = inputFile.nextInt();
    System.out.println("Reading d = " + d);


    if (!inputFile.hasNextInt()) {
       System.err.println("Reading file failed - invalid format (t)");
       break;
    }
    int t = inputFile.nextInt();
    System.out.println("Reading t = " + t);
    // Do some stuff
}

This way, you will avoid the NoSuchElementException, and the application will terminate gracefully. You will get the debugging output on the console. It will also print out what exactly has been read from the file.

Dorian Gray
  • 2,913
  • 1
  • 9
  • 25
0

As Dorian said, you're missing some validation:

while(inputFile.hasNext()) // Tells you there is "at least" 1 more element.
{
    int s = inputFile.nextInt();   // Good
    int d = inputFile.nextInt();   // Not good if 's' has taken the last element
    int t = inputFile.nextInt();   // Same as above

    // rest of the code here...
}

I personnally don't like the 'while(true)' stuff, so here is my version.

while(inputFile.hasNextInt())  // I would use 'hasNextInt()' rather than 'hasNext()'
                               // This will make sure the next data can be cast to an Integer
{
    Integer d = null;
    Integer t = null;
    Integer s = inputFile.nextInt();

    if( inputFile.hasNextInt() {
        d = inputFile.nextInt();
        if( inputFile.hasNextInt() {
            t = inputFile.nextInt();
        }
    }

    // 's' will never be null.
    if( d != null && t != null ) {
        TravelInfo p = new TravelInfo(s, d, t);
        list.add(p);
        TravelInfo cls = new TravelInfo(s,d,t);
        cls.calcTime(t);
        cls.calcTime(s);
        cls.calcTime(d);

       // System.out.println("Time is " + cls.calcTime(t));

       /*for(int i=0; i<list.size(); i++)
       {
           list.get(i).print();
      */ }
        for(TravelInfo k : list)
            System.out.println(k);

        PrintWriter outputFile = new PrintWriter("Data.txt");
        outputFile.println(list);
        //outputFile.println();
        outputFile.close();
    }
    else if( inputFile.hasNext()) {
        // At this point, you there the remaining data cannot be safely cast to an Integer.
    }
    else {
       // Not enough data to process.
    }
}

public class TravelInfo {
    private int speed;
    private int distance;
    private int time;

    public TravelInfo(int s, int d, int t) {
        speed = s;
        distance = d;
        time = t;
    }
    public int calcTime(int time) {
        time = distance/speed;
        return time;
    }

    // Override toString() instead of using the default Object.toString()
    @Override
    public String toString() {
        // Return whatever 'String' you want
        return String.format( "%d, %d, %d", speed, distance, time );
    }
}
  • I tried this and am still getting the same output of [cw7_3.TravelInfo@42a57993 like 20 times – Nitro May 03 '19 at 02:05
  • @Nitro What is your expected output? `System.out.println(k);` is the same as `System.out.println( k.toString());`. Since you don't override `toString()`, it calls `Object.toString()` – Yanick Poirier May 03 '19 at 20:41