retrieving a random word from a txt file and getting no output, and no compiler error java

StackOverflow https://stackoverflow.com/questions/21620034

  •  08-10-2022
  •  | 
  •  

Question

i cannot change the shell of the program, the end goal is to choose a random word from a list of words in a txt file. i've scanned through this many many times, gone through the code one by one, tried many different things, but every time i run it, it compiles without a problem but i never get any output. i've even tried inserting some output in the private functions, but to no avail. can anyone see what is wrong with my code or can explain to me what is happening?

import java.util.*;

    class PartOfSpeech
    {
      private String[] words;
      private Random random;
      private String filename;

      public PartOfSpeech(String filename)
      {
        this.filename = filename;
        this.read();
      }
      //this picks a random number and uses that number for the index of the array for which to return
      public String getRandomWord()
      {
        int index;
        index = random.nextInt(this.getCount());
        return words[index];
      }
      //this gets a count of how many lines of txt are in the file
      private int getCount()
      {
        Scanner fr = new Scanner(this.filename);
        int count = 0;
        while(fr.hasNextLine())
        {
         count++;
        }
       return count; 
      }
      //this creates a scanner and inserts each word from the txt file into an array
      private void read()
      {
        Scanner fr = new Scanner(this.filename);
        for(int i=0; i<this.getCount(); i++)
        {
         words[i] = fr.nextLine(); 
        }
      }

      public static void main(String[] args)
      {
        PartOfSpeech n = new PartOfSpeech("nouns.txt");
        System.out.print(n.getRandomWord());
      }
    }
Was it helpful?

Solution

Constructor Scanner(String source) actually parse the content of the source string, instead of treating it as a file name, You need

new Scanner(new File(fileName))

OTHER TIPS

I would suggest reconsidering your structure. You don't know how many words there are going to be in the file, so you should probably be using a Collection<String> as opposed to some fixed String[], to avoid iterating more than once. Perhaps you could try something like:

import java.io.File;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class PartsOfSpeech {

    private final List<String> words;
    private final File file;

    private int index;

    public PartsOfSpeech(final String filePath){
        words = new LinkedList<>();

        file = new File(filePath);
        read();

        Collections.shuffle(words);
    }

    private void read(){
        try{
            final Scanner input = new Scanner(file, "UTF-8");
            while(input.hasNextLine())
                words.add(input.nextLine());
            input.close();
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    public String getRandomWord(){
        if(index == words.size()){
            index = 0;
            Collections.shuffle(words);
        }
        return words.isEmpty() ? null : words.get(index++);
    }

    public static void main(String[] args){
        final PartsOfSpeech pos = new PartsOfSpeech("noun.txt");
        System.out.println(pos.getRandomWord());
    }
}

According to the Oracle documentation, you should use a new File as argument to Scanner.

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html

  private void read()
  {
    Scanner fr = new Scanner(new File(this.filename));
    for(int i=0; i<this.getCount(); i++)
    {
     words[i] = fr.nextLine(); 
    }
  }

Unrelated to the question, but you should really think about rewriting this function:

  //this gets a count of how many lines of txt are in the file
  private int getCount()
  {
    Scanner fr = new Scanner(this.filename);
    int count = 0;
    while(fr.hasNextLine())
    {
     count++;
    }
   return count; 
  }

When you read the file once to get all the words, you should update the count value there instead of reopening the file multiple times in getCount. If the file change, the count will be different from the amount of items inside words.

I'd refactor your code to something like this with an ArrayList instead of []:

  private void read()
  {
    Scanner fr = new Scanner(new File(this.filename));

    // reloading the file should clear the collection first
    words.clear()

    while(fr.hasNextLine())
    {
     words.add(fr.nextLine()); 
    }
  }

  private int getCount()
  {
   return words.size(); 
  }

And you can probably ditch completely getCount if it's not used anywhere and only use words.length. When calling multiple time the read function you should clear the collection if words could be added in between. Otherwise, you could skip all elements until the line you were at already and then add more elements to the collection.

  1. Your instance variable random is uninitialized, you will get NPE.
  2. Use new File(this.filename) as other people have suggested.
  3. Your getCount method is stuck in an infinite loop because you did not call Scanner.next().
  4. Use Collections object as suggested by others.
  5. You don't need to loop through the entire list every time you need to get the count.
  6. It is a good practice to minimize use or totally avoid using instance variables.

I would suggest to read your file into a list of Strings just once. then your count method simply would be calling size() on your list. Here is a method you could use to read your file and parse it into a list of Strings:

    public List<String> readFile(String filePath) throws IOException {
    List<String> result = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(
                    new FileInputStream(filePath)))) {
        String line;
        while ((line = reader.readLine()) != null) {
            result.add(line.replace("\n", ""));
        }
    }

    return result;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top