0

I'm having trouble writing a program for my Java class. The assignment's instructions are as follows:

"File Letter Counter:
Write a program that asks the user to enter the name of a file, and then asks the user to enter a character. The program should count and display the number of times that the specified character appears in the file. Use Notepad or another text editor to create a sample file that can be used to test the program."

The text file my professor provided us to test this program has 1307 lines of randomly cased and placed letters that this program has to go through and, for whatever reason, I can't seem to get this program to work right. I've tried using things outside of what we've learned so far in class and in the book, but I'm beyond lost.

Sample input:

f
d
s
h
j

Here's my code so far (compiled in NetBeans 23):

package filelettercounter;

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

public class FileLetterCounter {

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

        Scanner keyboard = new Scanner(System.in);
        
        System.out.print("Enter the file name: ");
        String filename = keyboard.nextLine();
        
        File file = new File(filename);
        Scanner inputFile = new Scanner(file);
        
        do {
            
            int counter = 0;
            String line = inputFile.nextLine();
            
            System.out.print("Enter a character: ");
            String character = inputFile.nextLine();
            
            if(line.contains(character)) {
                counter++;
            }
            
            System.out.println("The character " + character + " appears " +
                    counter + " times in the file.");
            
            }while(inputFile.hasNext());
        
        inputFile.close();
        
        }
    }

The output prints all 1307 lines showing that they each appear 0 times...

   Enter a character: The character f appears 0 times in the file.
   Enter a character: The character d appears 0 times in the file.
   Enter a character: The character s appears 0 times in the file.
   Enter a character: The character h appears 0 times in the file.
   Enter a character: The character j appears 0 times in the file.

...with an exception thrown most of the way down the output.

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1660)
    at filelettercounter.FileLetterCounter.main(FileLetterCounter.java:31)

The output I need to achieve is something like this:

Enter the file name: "filename"
Enter a character: "character"
The character (character) appears (number of times) times in the file.

Regarding input from any of you who are infinitely more experienced than I am, I'm not supposed to be doing anything fancy. The farthest we've gotten through as a class has been the various loops (for, if/else if/else, do-while, while), accumulating variables, etc. It is as basic as basic gets. So, please no lists or arrays or delimiters, or anything crazy like that.

6
  • Shouldn't you be prompting for the character only once? Commented Sep 26, 2024 at 15:26
  • 1
    I expect you would learn more if, instead of, or before asking here, you run this code in a debugger. As one of the answers in the linked question says, Using a debugger is an expected basic skill. Also, if you were not able to find the problem by debugging, including something about your effort might improve the question. And, finally, consider reading the file one character at a time. Commented Sep 26, 2024 at 15:58
  • @g00se I had that same thought. It could be OP wants to allow multiple runs until the user exits but it's not mentioned in his objective. Commented Sep 26, 2024 at 15:58
  • @Aro then the whole main method would need to be looped - and you still wouldn't need to ask for a character more than once per that loop Commented Sep 26, 2024 at 16:08
  • @g00se Definitely. I wonder if OP took the format of a previous assignment when starting this one-- it feels like it could be a copy-paste-modify situation. All of the elements are there just in the wrong places. Commented Sep 26, 2024 at 16:16

3 Answers 3

0

Understanding the exception

Let's start with the error;

It's decently descriptive with No line found. Your code at FileLetterCounter.java:31 is probably not the same line in your example, I'll assume it points to the inputFile.nextLine(); line.

This line is the place the issue is happening in your code so it's a good idea to start there.

Next we see the method call that is throwing within your code, Scanner.nextLine(). The docs for nextLine state the following:

public String nextLine()

Advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.

Since this method continues to search through the input looking for a line separator, it may buffer all of the input searching for the line to skip if no line separators are present.

Returns: the line that was skipped

Throws:

  • NoSuchElementException - if no line was found
  • IllegalStateException - if this scanner is closed

Since you're seeing this error, maybe the input really doesn't have any line to be found?

Solution

Let's go over the pseudo-code:

get the file and input streams ready.
loop (at least once) while the scanner has another token in its input:
    ...

At this point, you should check everything is working. Maybe start by printing out each token with Scanner.next(). Now continuing with the pseudo-code:

loop (at least once) while the scanner has another token in its input:
    set a counter to zero.
    advances scanner past the current line and returns the input
    prompt the user for a character.
    if the collected line contains an instance of the character,
        then increment counter by one.
    print out the counter.
end loop and start again using the same scanner.

Here's a few questions that may help:

  1. If we only increment the counter by 1 before printing the results, why would it be anything other than 0 or 1?
  2. If we only advance our scanner forward through the lines, what would happen to the count if some of the characters are only found in previous lines?
  3. What happens if the user keeps prompting multiple times, would we run out of lines?
  4. Why are we looping over lines? Would it be any different if we just looped over characters? Who knows, maybe the user wants to count the number of new-line characters.
  5. Why is the outer loop checking if the scanner has more tokens with hasNext() but inside the loop the entire line is consumed with nextLine()?

So in short, there are several logic errors here. The first one you're asking about is the use of the scanner. You've got another with the counter, and another potential one with how the loop is structured.

If you answer those questions and talk through some new pseudo code you should have a working solution.

Extra take-aways

When learning to coding, run often. Add 3-5 lines, maybe a println to debug, test it, and repeat.

Pseudo code is your friend. In this case, there are logic errors in a few places that would be caught by talking through what you want to do then validating the program is doing what you expect.

Sign up to request clarification or add additional context in comments.

Comments

0

Three things that you can fix:

  1. Your counter variable is reset for each iteration

  2. There can be more than one occurrence of the target character in each line

  3. The output message should only be displayed after you have iterated through all lines

Comments

-1

If your file is in the windows, enter a directory like D:\rajnish\test.txt. As you told this file contains a single character in every line, such as A C z Use the below code, it will work.

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

public class FileReading {

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

        Scanner keyboard = new Scanner(System.in);

        System.out.print("Enter the file directory: ");
        String filename = keyboard.nextLine();

        File file = new File(filename);
        Scanner inputFile = new Scanner(file);

        System.out.print("Enter a character: ");
        String character = keyboard.nextLine();

        int counter = 0;
        while (inputFile.hasNext()) {

            String line = inputFile.nextLine();

            if (line.equalsIgnoreCase(character)) {
                counter++;
            }

        }
        System.out.println("The character " + character + " appears " + counter + " times in the file.");

        inputFile.close();
        keyboard.close();

    }
}

3 Comments

As you told this file contains a single character in every line, Actually what was said was randomly cased and placed (my emphasis) so that might not work. In any case, there's a general solution that doesn't rely on any assumptions
Looks like this solution only addresses the prompting multiple times. This example still would throw the same error, yes? It's looping while hasNext() but pulling an entire line. Also has the counter logic error.
It will not throw the error. I checked running it on the Eclipse.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.