(java)尝试读取txt文件并计算每个单词的出现次数

igsr9ssn  于 2021-06-30  发布在  Java
关注(0)|答案(1)|浏览(427)

我应该写一个程序来读取一个叫做mobydick.txt的文件。这个文件包含了《白鲸》这本书的全部内容。mobydick.txt文件如下所示
我必须读取文件,显示文件中的每个唯一单词,然后显示每个唯一单词的出现次数。
输出应如下所示:
字数
43岁
鲸鱼12
93号船
这是我目前的代码:

import java.util.*;
import java.io.*;
public class Main
{
    public static void main(String[] args) throws IOException
    {
        //Create input stream & scanner
        FileInputStream fin = new FileInputStream("mobydick.txt");
        Scanner fileInput = new Scanner(fin);

        //Create Arraylist
        ArrayList<String> words = new ArrayList<String>();
        ArrayList<Integer> count = new ArrayList<Integer>();

        //Read through file and find the words
        while(fileInput.hasNext()) 
        {
            //Get next word
            String nextWord = fileInput.next();
            //Determine if the word is in the arraylist
            if(words.contains(nextWord))
            {
                int index = words.indexOf(nextWord);
                count.set(index, count.get(index) + 1);
            }
            else
            {
                words.add(nextWord);
                count.add(1);
            }

        }
        //close
        fileInput.close();
        fin.close();
        System.out.println("WORDS COUNT");
        //Print out the results
        for(int i = 0; i < words.size(); i++)
        {
            System.out.print(words.get(i) + "      " + count.get(i) + "\n");
        }

    }
}

然而,当我运行这段代码时,我得到了一个奇怪的输出。
这很奇怪,因为如果我为这样一个更小更简单的文本文件运行相同的代码,那么输出看起来就像我想要的那样。
mobydick.txt有什么问题吗?

kxe2p93d

kxe2p93d1#

只需查看文本输入文件。例如,它包含, ago-never . 程序员使用的计算机工具往往非常愚蠢,因为美国程序员需要它们非常简单。扫描器按空格分割。句号。 - 不是空白。扫描仪尽职尽责地给你 ago-never 作为一个标记。如果书中有 Cosmic said: "Sheesh, this coding stuff is hard, man!". ,然后这些是scanner将提供给您的令牌:

Cosmic
said:
"Sheesh,
this
coding
stuff
is
hard,
man!".

这显然不是你想要的。你想举个例子 man . 不是 man!". .
第二个问题是文本文件是文件,因此是bag-o-bytes。字节不是字符。所以,当你把你的文件变成一个扫描器时,你隐含地要求计算机对如何做到这一点大刀阔斧:它将使用“平台默认编码”,也就是javaese,意思是“永远不要你想要的”。这里没有简单的答案。有人需要调查或者告诉你编码是什么。可能是utf-8。在这种情况下,你必须告诉java:

new Scanner(fin, "UTF-8")

你没有这样做,所以java选择了“平台默认编码”,这是一种任意的、通常是错误的选择,因此类似于“ha”ägen dasz的错误-只有最基本的字符在错误的字符集编码下才能在转换中存活。
至于如何解决第一个问题,可能您真正需要的只是告诉scanner您希望“令牌之间的东西”是“任意数量的非字母”。定界符是一个regexp,它大概是一个你还没学过的概念;这很复杂。正则表达式 \W+ 表示“1个或多个‘非单词’字符”的概念,作为分隔符意味着感叹号、引号、圆点、换行符的序列-都会作为分隔标记的事物而消失。-也不是一封信,所以, ago-never 在输入文件中,将给您两个标记:ago和never。
您仍然应该将输入小写,扫描仪无法为您执行此操作。
要设置分隔符:

scanner.useDelimiter("\\W+"); // double backslash. That's not a typo.

编辑:使用此答案 [^a-zA-Z]+ 但正如@vgr在评论中指出的, \\W+ 更容易理解;一般来说,它可能更为地道。

相关问题