题目要求
按行读取english.txt ,并在该行的后面尾加上该英语句子中含有的单词数目,然后再将该行写入到一个名字为englishCount.txt的文件中。统计单词个数以及单词中的每个字母出现的频率,将每个单词出现的频率显示在一个窗口里面,按照单词出现的频率从高到低进行排列。单词个数以及单词出现频率一起写在同一个文件里面。
类的设计思想与设计原理
1.文件路径指定:通过指定文件路径filePath,明确了要分析的文本文件的位置。这使得程序可以针对不同的文件进行分析,只要修改这个路径即可,具有一定的灵活性。
2.文件读取部分:
- 使用try-with-resources语句来自动管理资源,确保在读取文件后正确关闭资源。这种方式可以避免资源泄漏的问题,提高程序的可靠性。
- 创建BufferedReader对象,结合FileReader来逐行读取文本文件。逐行读取的方式可以有效地处理大型文件,避免一次性将整个文件加载到内存中,高程序的性能和稳定性。
- 在读取每一行文本后,首先通过 trim 方法去除行首和行尾可能存在的空白字符,然后使用 split 方法以空格为分隔符拆分单词,从而统计出该行的单词个数。接着将该行文本转换为小写字母形式,以便后续统一统计字母出现频率时不区分大小写。
3.单词个数统计部分:
- 对于每一行文本,首先使用trim()方法去除两端的空白字符,这可以确保准确统计单词个数,避免因为行首或行尾的空白字符而导致错误的统计结果。
- 如果该行不为空,使用split(" ")方法将该行按照空格分割成单词数组,数组的长度即为该行的单词个数。这种方式简单直观,符合通常对英文句子中单词的定义(以空格分隔)。
- 输出该行文本和其中的单词个数,为用户提供直观的信息反馈,让用户了解每一行的单词数量情况。
4.字母频率统计部分:
- 创建一个Map<Character, Integer>(letterFrequencyMap)来存储每个字母及其出现的次数。选择Map数据结构是因为它可以方便地存储键值对,其中字母作为键,出现次数作为值。这样可以快速地查找和更新每个字母的出现次数。
- 将当前行转换为小写字母,以便统一处理。这可以确保无论原始文本中的字母是大写还是小写,都被视为同一个字母进行统计,提高统计的准确性。
- 遍历当前行的每个字符,如果字符是字母,就在映射中更新该字母的出现次数。使用Character.isLetter(c)方法来判断字符是否为字母,确保只统计字母的出现次数,排除其他非字母字符的干扰。
- 通过letterFrequencyMap.getOrDefault(c, 0) + 1这种方式,如果字母已经在映射中出现过,就获取其当前出现次数并加 1;如果字母还未出现过,就将其初始出现次数设为 0 后加 1。这种方式简洁高效,避免了重复的判断和初始化操作。
5.排序输出部分:
- 将字母频率映射转换为List<Map.Entry<Character, Integer>>(frequencyList),以便进行排序操作。将映射转换为列表利用 Java 集合框架中的排序对字母频率进行排序。
- 使用Collections.sort(frequencyList, (e1, e2) -> e2.getValue() - e1.getValue())方法根据字母出现次数从高到低对列表进行排序。这里使用了 Java 的 Lambda 表达式作为比较器,比较两个Map.Entry对象的值(即字母的出现次数),返回值为正数表示第一个对象的出现次数小于第二个对象,负数表示相反,零表示相等。这种排序方式可以确保字母按照出现频率从高到低排列。
- 遍历排序后的列表,输出每个字母及其出现的频率。这为用户提供了最终的分析结果,让用户清楚地了解文件中各个字母的出现频率情况。
6.异常处理部分:使用catch块捕获IOException异常,这是文件读取过程中可能出现的异常。如果文件读取过程中出现错误,输出错误信息,为用户提供明确的错误提示,方便用户进行问题排查和处理。
7.统计原理:结果展示原理(可视化部分):使用 JavaFX(或 Swing)的原理:当扩展代码添加可视化界面时,无论是使用 JavaFX 还是 Swing,都是基于它们提供的图形用户界面(GUI)组件库来构建窗口、表格等展示元素。例如,使用 JavaFX 时,通过创建 TableView 以及对应的列,并将统计结果数据转换为可观察列表来填充表格,使得数据能够在窗口中以表格形式清晰展示。使用 Swing 时,创建 JTable 并设置二维数组形式的数据和表头,再配合 JScrollPane 和 JFrame 等组件来构建一个可滚动查看的窗口展示效果。这些 GUI 组件遵循各自的布局和数据绑定原理,能够将处理后的统计结果以直观的视觉形式呈现给用户。
8.排序原理:在统计完字母出现频率后,将 Map 中的键值对转换为 List<Map.Entry<Character, Integer>> 形式的列表,然后使用 Collections.sort 方法并通过自定义的比较器(如 (e1, e2) -> e2.getValue() - e1.getValue())对列表进行排序,使得字母按照出现频率从高到低的顺序排列,这样在展示结果时能够更清晰地呈现出字母使用频率的高低情况。
9.功能模块化与独立性:在原有的代码基础上增加写入文件的功能时,尽量保持各个功能模块的相对独立性。原代码主要实现了从文本文件读取内容、统计字母频率以及通过图形界面展示结果的功能。新增的写入文件功能作为一个相对独立的模块,在不影响原有功能正常运行的前提下,实现将统计结果准确地写入到指定文件中,使得整个程序的功能更加丰富和完善。
设计源码
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class EnligshCount {public static void main(String[] args) {// 指定要读取的文本文件路径String filePath = "E:\\java idea\\java_homework\\src\\english.txt";// 指定要写入统计结果的文件路径String outputFilePath = "E:\\java idea\\java_homework\\src\\englishCount.txt";try (BufferedReader br = new BufferedReader(new FileReader(filePath));FileWriter fw = new FileWriter(outputFilePath)) {// 创建一个映射,用于存储字母及其出现的次数Map<Character, Integer> letterFrequencyMap = new HashMap<>();// 逐行读取文件内容String line;while ((line = br.readLine())!= null) {// 统计这句话的单词个数int wordCount = line.trim().isEmpty()? 0 : line.trim().split(" ").length;// 输出该行文本和其中的单词个数System.out.println(line + " 句子中单词个数为: " + wordCount);// 将当前行转换为小写字母,以便统一处理line = line.toLowerCase();// 遍历当前行的每个字符for (char c : line.toCharArray()) {// 如果字符是字母if (Character.isLetter(c)) {// 在映射中更新该字母的出现次数letterFrequencyMap.put(c, letterFrequencyMap.getOrDefault(c, 0) + 1);}}// 将单词数量写入到输出文件fw.write(line + " 句子中单词个数为: " + wordCount + "\n");}// 将字母频率映射转换为列表,以便进行排序操作List<Map.Entry<Character, Integer>> frequencyList = new ArrayList<>(letterFrequencyMap.entrySet());// 根据字母出现次数从高到低对列表进行排序Collections.sort(frequencyList, (e1, e2) -> e2.getValue() - e1.getValue());// 将字母频率信息写入到输出文件fw.write("字母出现频率统计:\n");for (Map.Entry<Character, Integer> entry : frequencyList) {fw.write(entry.getKey() + " : " + entry.getValue() + "\n");}// 创建用于展示结果的二维数组Object[][] data = new Object[frequencyList.size()][2];for (int i = 0; i < frequencyList.size(); i++) {Map.Entry<Character, Integer> entry = frequencyList.get(i);data[i][0] = entry.getKey();data[i][1] = entry.getValue();}// 创建表头数组String[] columnNames = {"字母", "出现频率"};// 创建JTable并设置数据和表头JTable table = new JTable(data, columnNames);// 创建滚动面板并将JTable添加进去JScrollPane scrollPane = new JScrollPane(table);// 创建JFrame窗口并设置相关属性JFrame frame = new JFrame("英语文本统计结果");frame.add(scrollPane);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(300, 250);frame.setVisible(true);} catch (IOException e) {// 如果文件读取或写入过程中出现错误,输出错误信息System.out.println("文件读取出错: " + e.getMessage());}}
}