5

I am trying to delete a specific node from a linked list. I am trying to call my method removeNode, but it is giving me this error when I call it to get the user input. Any advice on how to fix this would be greatly appreciated!

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Unknown Source)
    at LinkedList.removeNode(LinkedList.java:123)
    at fileIn.<init>(fileIn.java:22)
    at fileIn.main(fileIn.java:13)

LinkedList class:

import java.util.Scanner;

public class LinkedList {

    public LinkedListNode front;

    public LinkedList() {
        this.front = null;
    }

    public void insertBack(String data)
    {
        if(front == null){
            front = new LinkedListNode(data);
        }
        else{
            LinkedListNode newNode = new LinkedListNode(data);
            LinkedListNode current = front;

            while(current.getNext() != null){
                current = current.getNext();
            }
            current.setNext(newNode);
        }
    }//end insertBack

    public void addAfter(LinkedListNode spot, String data)
    {
        LinkedListNode newNode;

        newNode = new LinkedListNode(data);

        newNode.next = spot.next;
        spot.next = newNode;
    }//end addAfter

    public void addBefore(LinkedListNode spot, String data)
    {

    }//end addBefore

    public void deleteAfter(LinkedListNode spot)
    {
        LinkedListNode nextNode;

        nextNode = spot.next;
        spot.next = nextNode.next;
    }//end deleteAfter


    public String showList()
    {
        sortList();
        //^-- Will sort the sum but not the nodes

        int i = 0;
        String retStr = "The nodes in the list are:\n";
        LinkedListNode current = front;
        while(current != null){
            i++;
            retStr += "Node " + i + " is: " + current.getData() + " and the sum is: " + current.getSum() + "\n";
            current = current.getNext();
        }

        return retStr;
    }

    public LinkedListNode findTail()
    {
        LinkedListNode current = front;
        while(current.getNext() != null){
            current = current.getNext();
        }
        return current;
    }//end findTail

    public LinkedList sortList()
    {
        LinkedListNode current = front;
        LinkedListNode tail = null;

        while(current != null && tail != front )
        {
            LinkedListNode next = current;

            for( ; next.next != tail;  next = next.next)
            {
                if(next.sum >= next.next.sum)
                {
                    long temp = next.sum;
                    String temp2 = next.data;

                    next.sum = next.next.sum;
                    next.data = next.next.data;

                    next.next.sum = temp;
                    next.next.data = temp2;
                }
            }

            tail = next;
            current = front;
        }

        return this;
    }

    public void removeNode(){

    String searchedNode;

    Scanner in = new Scanner(System.in);
    System.out.println("Enter the name you would like to remove from the list: ");
    searchedNode = in.nextLine();
    in.close();
        LinkedListNode previous = null;
        LinkedListNode current = front;

            //while there is something in the list nodes
             while (current != null)
             {
                //if the data of current is equal to the node being searched
                if(current.data.equals(searchedNode))
                {
                  //set current to the node after current
                  current = current.next;
              //if previous is equal to null(which it is)
              if (previous == null)
                  {
                  //set previous equal to current
                  previous = current;
                  }

                  else previous.next = current;
                } else {
                  previous = current;
                  current = current.next;
            }
        } //end while
    }
}

fileIn class:

import java.util.Scanner;
import java.io.*;

public class fileIn
{
   LinkedListNode front;
   LinkedList myList = new LinkedList();
   String fname;

   public static void main(String[] args)
    {
       fileIn f = new fileIn();
   }//end main


   public fileIn()
   {
      getFileName();
      readFileContents();
      System.out.print(myList.showList());
      myList.removeNode();
   }//end fileIn

   public void readFileContents()
    {
        boolean looping;
        DataInputStream in;
        String line;

        /* Read input from file and process. */
        try
        {
            in = new DataInputStream(new FileInputStream(fname));

            looping = true;
            while(looping)
             {
                /* Get a line of input from the file. */
                if (null == (line = in.readLine()))
                {
                    looping = false;
                    /* Close and free up system resource. */
                    in.close();
                }//end if
                else
                {
                myList.insertBack(line);
                }//end else
            } /* End while. */
        } /* End try. */

        catch(IOException e)
        {
            System.out.println("Error " + e);
        } /* End catch. */
    }//end readFileContents

     public void getFileName()
     {
        Scanner in = new Scanner(System.in);

        System.out.println("Enter file name please.");
        fname = in.nextLine();
        in.close();
     }//end getFileName

}//end class fileIn
Shawn
  • 1,993
  • 11
  • 40
  • 79
  • How are you running this program? Through an IDE? – Jason C Nov 07 '13 at 04:31
  • I've done some research an looked into using... while(in.hasNextLine()){ searchedNode = in.nextLine(); } but I don't understand how to acces that value outside of that while statement – Shawn Nov 07 '13 at 04:36
  • 1
    Go to the run configuration for your project; go to the "Common" tab. Be sure that "Allocate Console" is checked and "File" is unchecked down in the "Standard Input and Output" area. – Jason C Nov 07 '13 at 04:36
  • Allocate Console is checked and File is unchecked – Shawn Nov 07 '13 at 04:37

2 Answers2

12

The problem is you are closing System.in (Scanner.close() closes the underlying stream). Once you do that, it stays closed, and is unavailable for input. You don't normally want to do that with standard input:

String searchedNode;
Scanner in = new Scanner(System.in);
System.out.println("Enter the name you would like to remove from the list: ");
searchedNode = in.nextLine();
// in.close(); // <-- don't close standard input!

Also, for future reference, you should try to create more minimal test cases. It will help you debug and also remove a lot of noise from your questions. :-)

Jason C
  • 34,234
  • 12
  • 103
  • 151
  • 1
    Funny story. I actually removed that in.close because I thought that may be interfering also. So i just removed it again when you said it and still got the error. So I went to the fileIn class and removed that in.close in the getFileName() method and now it works great. Thanks for the answer and do you know where I could go to get good lessons on debugging? – Shawn Nov 07 '13 at 04:42
  • Thank you for the help and marked as answer – Shawn Nov 07 '13 at 04:44
  • 1
    I don't know any particular debugging resources off the top of my head but I'm sure they are out there if you look. A lot comes from experience, a lot comes from a general ability to recreate, isolate, and narrow down the source of a problem. In your case one way to narrow it down is to notice that the exception is coming from the scanner, wasn't related to your other code, and try to create a tiny program to recreate it. In more complex cases using the debugger in Eclipse, strategically printing things out, etc., can help. – Jason C Nov 07 '13 at 04:44
0

As per How to solve java.util.NoSuchElementException in Java (as well as common sense) use the appropriate kind of hasNext method before each next.

In your particular case, it will be something like this:

if (in.hasNextLine) {
    in.nextLine();
}
Jason C
  • 34,234
  • 12
  • 103
  • 151
PM 77-1
  • 11,712
  • 18
  • 56
  • 99
  • 1
    That test would always fail, as he has closed `System.in`. – Jason C Nov 07 '13 at 04:42
  • @JasonC : He creates brand new `Scanner` object before getting *nextLine* and closes after. At the time of the test it's still open. – PM 77-1 Nov 07 '13 at 04:46
  • `Scanner.close()` closes the underlying stream if it implements `Closeable`, which `System.in` does -- it ultimately calls `System.in.close()`. See http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#close(). The next time he creates a `new Scanner(System.in)`, he creates it on an already-closed underlying stream, which is why the problem is occurring. `hasNextLine()` would return false at any point after the first time his program closes the stream. – Jason C Nov 07 '13 at 04:48
  • @JasonC : If this were the case he would've gotten `IllegalStateException` (as the source you provided clearly states). Who cares what happened to the stream **after** the attempt to read from it? – PM 77-1 Nov 07 '13 at 04:52
  • 1
    Try it: `new Scanner(System.in).close(); System.out.println(new Scanner(System.in).hasNextLine());`. The source states that exception comes from using the *Scanner* after it is closed. He never does this. That exception is *not* a result of creating a new `Scanner` on an already-closed stream. Remember, there's a stream under there, and it's independent of the lifetime of any `Scanner` that is wrapped around it. `new Scanner(System.in).close()` closes `System.in`. Permanently. Subsequent Scanners on that stream do not reopen it. See also the problem's solution. – Jason C Nov 07 '13 at 04:54
  • OK. Got it. But it still does not explain [the particular exception he was getting](http://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html) which is "*Thrown by the nextElement method of an Enumeration to indicate that there are no more elements in the enumeration.*". – PM 77-1 Nov 07 '13 at 05:03
  • 1
    @PM77-1 In the JDK, for accurate exception documentation, you'd want to refer to the documentation of the throwing method. The documentation of the exception itself is extremely generic. You could argue that it isn't the best exception to be thrown (but to be fair it *is* an enumerator-style hasNext()/next() interface), but the fact is that it is the one that is thrown. See also the source for `Scanner.nextLine()`: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/Scanner.java#Scanner.nextLine%28%29 – Jason C Nov 07 '13 at 05:08
  • @JasonC : Yep, I found the code too. It took me a while to realize that the exception is thrown by the `nextLine` method itself and not directly from user code. It's clear now. Should I delete my question or could these comment exchange be of any use to someone else? – PM 77-1 Nov 07 '13 at 05:12
  • That is entirely up to you. :-) If they were useful to you they could certainly be useful to somebody else! – Jason C Nov 07 '13 at 05:46