0

This is a diary program which allows you to write something in your diary (obviously). After typing enter and pressing enter, the page closes and its gonna be safed in a list. My problem is that it only runs once when I have Pages(); in the main method, so I tried this loop. It doesnt work for me and i dont know why. Need some help

import java.util.ArrayList;
import java.util.Scanner;

public class NotizbuchKlasse{
    public static void Pages() {
        System.out.println("day 1 : Write something in your diary.");
        System.out.println("Write enter if you are done writing.");
        ArrayList<String> List = new ArrayList<String>();
        String ListInList;
        Scanner write = new Scanner(System.in);
        do {
            ListInList = write.next();
            List.add(ListInList);
        } while (! ListInList.equals("enter"));
        List.remove(List.size()-1);
        write.close();          
        System.out.println("This is now your page. Your page is gonna be created after writing something new.");
        System.out.println(List);
    }

    public static void main(String[]Args){
        boolean run = true;
        do{
            Pages();
        } while(run);
    } 
}

Error:

This is now your page. Your page is gonna be created after writing something 
new.
Exception in thread "main" [hello]
day 1 : Write something in your diary.
Write enter if you are done writing.
java.util.NoSuchElementException
    at java.util.Scanner.throwFor(Unknown Source)
    at java.util.Scanner.next(Unknown Source)
    at NotizbuchKlasse.Pages(NotizbuchKlasse.java:12)
    at NotizbuchKlasse.main(NotizbuchKlasse.java:24)
Code-Apprentice
  • 69,701
  • 17
  • 115
  • 226
SlimE
  • 45
  • 1
  • 4
  • 1
    Are you looking for [`write.hasNext()`](https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#hasNext--)? – Andy Turner Jul 15 '17 at 22:04
  • I am askin why the loop in the main thread does not work for the program – SlimE Jul 15 '17 at 22:09
  • `write.close();` closes Scanner but also stream which scanner was using so `System.in` which prevents you from reading from it again. So when you are using `next()` it throws NoSuchElementException. It is better to have one scanner for whole application which is handling `System.in`. You can create one in main method and pass it to other methods as argument. – Pshemo Jul 15 '17 at 22:17
  • I suggest that you learn about Java naming conventions. Typically class and interface names start with an uppercase letter and variable names start with a lower case letter. Also, the Java API has an interface named `List`, so this is not a good choice for a variable name. Instead you can use `list`. – Code-Apprentice Jul 15 '17 at 22:18

2 Answers2

4

You need to check whether there is something to read before you read it. You're not currently, and that's why you're getting a NoSuchElementException.

You do this via Scanner's has* methods.

For example:

    ArrayList<String> List = new ArrayList<String>();
    Scanner write = new Scanner(System.in);
    while (write.hasNextLine()) {
        String ListInList = write.nextLine();
        if (ListInList.equals("enter")) break;
        List.add(ListInList);
    }
    // No need to remove the last item from the list.

But also, I notice that you have a loop in your main method, where you call Pages() in that loop. If you close write, you also close System.in; once a stream is closed, you can't re-open it. So if you try to read things from System.in the next time you call Pages(), the stream is already closed, so there's nothing to read.

Simply don't call write.close(). You shouldn't close streams that you didn't open in general; and you didn't open System.in (the JVM did when it started up), so don't close it.

Andy Turner
  • 122,430
  • 10
  • 138
  • 216
  • I don't get it. Wouldn't the Scanner effectively keep reading off of stdin as long as "enter" is not put in? Why the hasNext() and when will it be false? – cst1992 Jul 15 '17 at 22:15
  • 1
    `hasNext()` will return false if the scanner does not have another token. This can happen, for example, if the stream is closed. – Andy Turner Jul 15 '17 at 22:20
  • @MoeA no, because that will result in `System.in` being closed afterwards. – Andy Turner Jul 15 '17 at 23:51
  • ...because you call that method in a loop. As I explain in the second half of my answer. – Andy Turner Jul 15 '17 at 23:55
0

You want to be using a while loop like this:

while (write.hasNextLine()) {
  ListInList = write.nextLine();
  if (doneWriting(ListInList)) { // Check for use of enter.
    break; // Exit the while loop when enter is found.
  }
  List.add(ListInList); // No enter found. Add input to diary entry.
}

where doneWriting() is a method (that you write!) which checks to see if the user has typed enter.

Here is the documentation for the next() method of Scanner. If you read it, you will see that it throws the exception you are getting when it runs out of tokens.

If you want a little bit more a casual explanation here is a question that was asked previously about next() versus nextLine().