0

我无法更改程序的外壳,最终目标是从 txt 文件中的单词列表中选择一个随机单词。我已经扫描了很多次,一一浏览了代码,尝试了许多不同的东西,但是每次运行它,它都可以毫无问题地编译,但我从来没有得到任何输出。我什至尝试在私有函数中插入一些输出,但无济于事。谁能看到我的代码有什么问题或者可以向我解释发生了什么?

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());
      }
    }
4

5 回答 5

1

Constructor Scanner(String source) 实际上是解析源字符串的内容,而不是把它当作文件名,你需要

new Scanner(new File(fileName))
于 2014-02-07T05:32:33.157 回答
1

根据 Oracle 文档,您应该使用new File作为 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(); 
    }
  }

与问题无关,但你真的应该考虑重写这个函数:

  //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; 
  }

当您读取文件一次以获取所有单词时,您应该更新那里的计数值,而不是在getCount. 如果文件发生变化,count里面的物品数量就会不同words

我会用 ArrayList 而不是 [] 将您的代码重构为这样的:

  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(); 
  }

如果getCount它没有在任何地方使用并且只使用words.length. 多次调用该read函数时,如果可以在其间添加单词,则应清除集合。否则,您可以跳过所有元素,直到您所在的行,然后将更多元素添加到集合中。

于 2014-02-07T05:34:42.650 回答
1

我建议重新考虑你的结构。您不知道文件中将包含多少个单词,因此您可能应该使用 aCollection<String>而不是 some fixed String[],以避免重复多次。也许您可以尝试以下方法:

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());
    }
}
于 2014-02-07T05:43:50.947 回答
0
  1. 您的实例变量 random 未初始化,您将获得 NPE。
  2. 像其他人建议的那样使用 new File(this.filename) 。
  3. 您的 getCount 方法陷入无限循环,因为您没有调用 Scanner.next()。
  4. 按照其他人的建议使用 Collections 对象。
  5. 每次需要获取计数时,您都不需要遍历整个列表。
  6. 尽量减少使用或完全避免使用实例变量是一个很好的做法。
于 2014-02-07T06:07:29.740 回答
0

我建议将您的文件读入字符串列表一次。那么您的 count 方法只会在您的列表中调用 size() 。这是一种可用于读取文件并将其解析为字符串列表的方法:

    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;
}
于 2016-02-02T19:59:54.160 回答