This is a small program written for a small assignment to check spelling. The assignment asks for the following output:
- A list of words that are misspelled in the file
- A count of the whitespace delimited words contained in the file
- For all words that appear in the file, a count of the number of times they appear. This should be in alphabetical order
- A list of the top five words in terms of frequencey of appearance from the file.
My program runs successfully. I just want to get some suggestions to improve it.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Scanner;
public class SpellChecker {
private final HashDict dict;
private final HashDict wordFile;
final static String dictionary = "dict.txt";
final static String file = ("big_flat_file.txt");
/**
* Constructor of spellChecker
*/
public SpellChecker() {
dict = new HashDict<>();
wordFile = new HashDict<>();
read(dictionary);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
SpellChecker checker = new SpellChecker();
int wordCount = checker.count(file);
System.out.println("The file contains following misspelled words: ");
checker.spellCheck();
System.out.println("The file contains " + wordCount + " words in total");
System.out.println();
System.out.println("The frequency of all words are listed below: ");
checker.wordFreq();
}
/**
* read dictionary into a hashed dictionary
*
* @param fileName the file of dictionary
*/
public void read(String fileName) {
File theFile = new File(fileName);
try {
Scanner reader = new Scanner(theFile);
while (reader.hasNext()) {
String input = reader.next();
dict.add(input, 0);
}
} catch (FileNotFoundException e) {
System.out.print("file not found");
}
}
/**
* add every word into a hashed dictionary as the key, its frequency as
* value, and count the total words
*
* @param fileName a given .txt file
* @return an integer of total words in the file
*/
public int count(String fileName) {
File theFile = new File(fileName);
int totalCount = 0;
try {
Scanner sc = new Scanner(theFile);
while (sc.hasNext()) {
int freq = 0;
String word = sc.next().replaceAll("[^A-Za-z]+", "").toLowerCase();
totalCount++;
if (wordFile.contains(word)) {
freq = (int) wordFile.getValue(word.toLowerCase());
}
freq++;
wordFile.add(word, freq);
}
} catch (FileNotFoundException ex) {
}
return totalCount;
}
/**
* Check every word in the file to see if it is misspelled by comparing it
* with the dictionary. Ignore all the single letters. Print out the word
* that is not contained in the dictionary
*/
public void spellCheck() {
Iterator traverse = wordFile.getKeyIterator();
while (traverse.hasNext()) {
String e = (String) traverse.next();
if (!e.matches("[A-Za-z]{1}")) {
if (!dict.contains(e)) {
System.out.println(e);
}
}
}
}
/**
* Count the time of all words appear in the file, and list them in
* alphabetical order.
* List top five words that appear most.
*/
public void wordFreq() {
Iterator traverse = wordFile.getKeyIterator();
ArrayList<String> list = new ArrayList<>();
int top1 = 0, top2 = 0, top3 = 0, top4 = 0, top5 = 0;
int top1Index = 0, top2Index = 0, top3Index = 0, top4Index = 0,
top5Index = 0;
while (traverse.hasNext()) {
String e = (String) traverse.next();
list.add(e);
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
}
// find the top 5 words that appear most frequent
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i) + " " + wordFile.getValue(list.get(i)));
int freq = (int) wordFile.getValue(list.get(i));
if (freq > top1) {
top1 = freq;
top1Index = i;
} else if (freq > top2) {
top2 = freq;
top2Index = i;
} else if (freq > top3) {
top3 = freq;
top3Index = i;
} else if (freq > top4) {
top4 = freq;
top4Index = i;
} else if (freq > top5) {
top5 = freq;
top5Index = i;
}
}
System.out.println();
System.out.println("The top 5 frequent used words in the file are");
System.out.println(list.get(top1Index) + " " + top1);
System.out.println(list.get(top2Index) + " " + top2);
System.out.println(list.get(top3Index) + " " + top3);
System.out.println(list.get(top4Index) + " " + top4);
System.out.println(list.get(top5Index) + " " + top5);
}
}
The HashDict
is my own written chained dictionary and is checked by my instructor. I am not going to put it here, but I will if somebody asks for it.
----------------------------------update code-------------------------------------- Following are my updated code based on suggestions I've got.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Scanner;
public class SpellChecker {
private final HashDict dict;
private final HashDict wordFile;
final static String dictionary = "dict.txt";
/**
* Constructor of spellChecker
*/
public SpellChecker() {
dict = new HashDict<>();
wordFile = new HashDict<>();
readDict(dictionary);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("What is the filename?");
String inputFileName = in.nextLine();
SpellChecker checker = new SpellChecker();
int wordCount = checker.loadFileAndCount(inputFileName);
checker.printMisspelledWords();
System.out.println();
System.out.println("The file contains " + wordCount + " words in total");
System.out.println();
checker.wordFreq();
}
/**
* readDict dictionary into a hashed dictionary
*
* @param fileName the file of dictionary
*/
public void readDict(String fileName) {
File theFile = new File(fileName);
try {
Scanner reader = new Scanner(theFile);
while (reader.hasNext()) {
String input = reader.next();
dict.add(input, 0);
}
} catch (FileNotFoundException e) {
System.out.print("file not found");
}
}
/**
* add every word into a hashed dictionary as the key, its frequency as
* value, and loadFileAndCount the total words
*
* @param fileName a given .txt file
* @return an integer of total words in the file
*/
public int loadFileAndCount(String fileName) {
File theFile = new File(fileName);
int totalCount = 0;
try {
Scanner sc = new Scanner(theFile);
while (sc.hasNext()) {
int freq = 0;
String word = sc.next().replaceAll("[^A-Za-z]+", "").toLowerCase();
totalCount++;
if (wordFile.contains(word)) {
freq = (int) wordFile.getValue(word.toLowerCase());
}
freq++;
wordFile.add(word, freq);
}
} catch (FileNotFoundException ex) {
System.out.println("File not found.");
}
return totalCount;
}
/**
* Check every word in the file to see if it is misspelled by comparing it
* with the dictionary. Ignore all the single letters. Print out the word
* that is not contained in the dictionary
*/
public void printMisspelledWords() {
Iterator traverse = wordFile.getKeyIterator();
System.out.println("The file contains following misspelled words: ");
while (traverse.hasNext()) {
String e = (String) traverse.next();
if (!(e.length() == 1 && Character.isLetter(e.toCharArray()[0]))) {
if (!dict.contains(e)) {
System.out.println(e);
}
}
}
}
/**
* Count the time of all words appear in the file, and list them in
* alphabetical order. List top five words that appear most.
*/
public void wordFreq() {
Iterator traverse = wordFile.getKeyIterator();
ArrayList<String> list = new ArrayList<>();
int[] topFreq = new int[5];
int[] topFreqIndex = new int[5];
while (traverse.hasNext()) {
String e = (String) traverse.next();
list.add(e);
}
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
System.out.println("The frequency of all words are listed below: ");
// print out all words and their frequencies, and
// find the top 5 words that appear most frequent
for (int i = 0; i < list.size(); i++) {
int freq = (int) wordFile.getValue(list.get(i));
System.out.println(list.get(i) + " " + freq);
for (int m = topFreq.length - 1; m >= 0; m--) {
if (freq > topFreq[m]) {
if (m == topFreq.length - 1) {
topFreq[m] = freq;
topFreqIndex[m] = i;
} else {
int tempFreq = topFreq[m];
int tempFreqIndex = topFreqIndex[m];
topFreq[m] = freq;
topFreqIndex[m] = i;
topFreq[m + 1] = tempFreq;
topFreqIndex[m + 1] = tempFreqIndex;
}
}
}
}
System.out.println();
System.out.println("The top 5 frequent used words in the file are");
for (int m = 0; m < topFreq.length; m++) {
System.out.println(list.get(topFreqIndex[m]) + " " + topFreq[m]);
}
}
}
Most of the changes are in the wordFreq method.
The output is like this:
run:
What is the filename?
big_flat_file.txt
The file contains following misspelled words:
// all misspelled words
The file contains 6629 words in total
The frequency of all words are listed below:
// all words and their frequency. TL
The top 5 frequent used words in the file are
of 262
and 248
to 246
the 183
167
One thing concerned me is that the last top frequent word is a blank space. The blank space also appears in the word count, so that it is not the topFreq method's problem. I am not sure why it is counted as a word.