[英](Java) Trying to read a txt file and count the number of occurrences for each word
我應該編寫一個程序來讀取名為 mobydick.txt 的文件。 該文件包含《白鯨記》這本書的全文。 mobydick.txt 文件看起來像這樣
我必須讀取文件,顯示文件中的每個唯一單詞,然后顯示每個唯一單詞的出現次數。
output 應如下所示:
字號
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");
}
}
}
然而,當我運行這段代碼時,我得到了一個奇怪的output 。
這很奇怪,因為如果我為這樣一個更小更簡單的文本文件運行相同的代碼,output 看起來就像我想要的一樣。
我在 mobydick.txt 上做錯了什么?
只需查看文本輸入文件。 例如,它包含ago-never
。 程序員的計算機工具往往非常愚蠢,因為我們程序員需要它們非常簡單。 掃描儀在空白處拆分。 時期。 -
不是空格。 Scanner 盡職盡責地為您提供ago-never
作為單一令牌。 如果書中包含Cosmic said: "Sheesh, this coding stuff is hard, man.".
,那么這些是掃描儀將為您提供的令牌:
Cosmic
said:
"Sheesh,
this
coding
stuff
is
hard,
man!".
這顯然不是你想要的。 你想要例如man
。 不是man.".
第二個問題是文本文件是文件,因此是bag-o-bytes。 字節不是字符。 所以,當你把你的文件變成掃描儀時,你隱含地要求計算機對如何做到這一點進行猛烈抨擊,而且它會:它將使用“平台默認編碼”,這是 java-ese 用於'從來沒有你想要的'。 這里沒有簡單的答案。 有人需要調查或告訴你編碼是什么。 可能是 UTF-8。 在這種情況下,你必須告訴 java:
new Scanner(fin, "UTF-8")
你沒有,所以 java 選擇了“平台默認編碼”,這是一些隨意且通常錯誤的選擇,因此像“Haägen Dasz”這樣的東西會搞砸 - 只有最基本的字符往往會在使用錯誤字符集編碼的轉換中幸存下來。
至於如何解決第一個問題,您可能真正需要的只是告訴掃描儀您希望“令牌之間的東西”是“任意數量的非字母”。 定界符是一個正則表達式,它可能是一個你還沒有學過的概念; 這很復雜。 正則表達式\W+
表示:“1 個或多個'非單詞'字符”的概念,並且作為分隔符意味着感嘆號、引號、點、換行符的序列 - 都作為分隔標記的事物而消失。 - 也不是字母,因此,輸入文件中的ago-never
將給您兩個標記:ago 和 never。
您仍然應該將輸入小寫,掃描儀無法為您執行此操作。
要設置分隔符:
scanner.useDelimiter("\\W+"); // double backslash. That's not a typo.
編輯:這個答案以前使用過[^a-zA-Z]+
,但正如@VGR 在評論中指出的那樣, \\W+
更容易理解; 一般來說,它可能更慣用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.