zoukankan      html  css  js  c++  java
  • 词频统计

       
    这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/computer-science-class3-2018/homework/11879
    这个作业有什么要求 https://edu.cnblogs.com/campus/zswxy/computer-science-class3-2018/homework/11879
    学号 20188476
    • WordCount

      • Git项目地址

      • PSP表格

      • 代码规范链接

      • 解题思路描述

      • 设计与实现过程

      • 部分异常处理说明

      • 心路历程与收获

    Git项目地址

    https://gitee.com/BX881206/project-java/tree/master

    PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 1450 3000
    • Estimate • 估计这个任务需要多少时间 1440 2880
    Development 开发 720 960
    • Analysis • 需求分析 (包括学习新技术) 30 90
    • Design Spec • 生成设计文档 20 10
    • Design Review • 设计复审 20 10
    • Coding Standard • 代码规范 (为目前的开发制定合适的规范) 20 20
    • Design • 具体设计 120 250
    • Coding • 具体编码 640 720
    • Code Review • 代码复审 30 30
    • Test • 测试(自我测试,修改代码,提交修改) 40 60
    Reporting 报告 30 15
    • Test Report • 测试报告 10 15
    • Size Measurement • 计算工作量 15 10
    • Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 30 25

    代码规范链接

    https://gitee.com/BX881206/project-java/blob/master/20188476/codestyle.md

    解题思路描述

    • 读取字符是一个一个读取输入的文件流,对其进行判断是否符合要求之后再进行计数(不符合要求的计数是无效的,必须对其进行判断)
    • 读取单词,可以使用正则表达式来匹配单词,并过滤掉无效字符,以单词-频率作为键值对保存在TreeMap中
    • 行数统计直接按行读取后使用trim()去掉空白字符后,再进行判断计数就可以了

    设计与实现过程

    • 类和函数关系图

    主要流程图

    部分异常处理说明

    1.通过CMD运行提示“编码GBK的不可映射字符”

    • 解决办法:查找了很多资料,收获了好几种方法,感觉最好用的是直接对.Java文件改编码方式

      2.使用命令行编译时,由于一开始的项目在SRC目录下有包,.java文件在包里,所以javac 命令要进入到.java文件目录也就是最里层才可以,生成的.class文件和.java文件在同一目录。而使用java命令时,则要进到SRC目录下,包名作为前缀名来使用,并且名称不带后缀,格式如:java 包名.java文件名 才可以运行,然后我就直接重新新建了一个文件,运行成功了.
    • 关键代码

    1.统计文件的字符数(对应输出第一行)

    • 思路:用了BufferedReader去读取文本,用while循环去判断读入字符是否合法,最后return读取的字符数(具体可见注释部分)
    • 独到之处:使用BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行的高效读取,而且可以指定缓冲区的大小
     public static int charNum(String filename) throws IOException  {
    		  //统计文件的字符数
    			int num = 0;		
    			BufferedReader br = new BufferedReader(new FileReader(filename));
    			int value = -1;// EOF标记文件末尾
    			while ((value = br.read()) != -1) {
    				//判断是否读到了文件末尾
    				if (value > 0 && value < 128 && value != 13) {
    					//不统计回车符,ASCII正常十进制范围0~127
    					num ++;
    				}			
    			}
    			br.close();		
    			return num;
    		}
    
    

    2.统计文件的单词总数(对应输出第二行),单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。

    • 思路:用了BufferedReader去读取文本,用正则表达式去判断匹配是否是有效单词,匹配成功则计数(具体可见注释部分)
    • 独到之处:用正则表达式,Pattern类,Matcher类方法去匹配是否是有效单词
    public static int wordNum(String filename) throws IOException  {
    			//统计单词总数
    			int num = 0;			
    			BufferedReader br = new BufferedReader(new FileReader(filename));
    			String separator = "[^A-Za-z0-9]";//分隔符
    			String regex = "^[A-Z a-z]{4,}[0-9]*$"; //正则判断每个数组中是否存在有效单词
    			Pattern p = Pattern.compile(regex);//使用Pattern.compile方法编译一个正则表达式,创建一个匹配模式
    			Matcher m = null;
    			String line = null;
    			String[] array = null;
    			while ((line  = br.readLine()) != null) {
    	            line = line.replaceAll("[(\u4e00-\u9fa5)]", "");// 用空格替换汉字
    	            line = line.replaceAll(separator, " "); // 用空格替换分隔符
    	            array = line.split("\s+"); // 按空格分割 →字符串数组                  
    	            for (int i = 0;i<array.length;i++) { 
    	            	m = p.matcher(array[i]);//进行匹配,看是否是有效单词
    	            	if (m.matches()) {//匹配成功
    	            		num++;
    	            	}
    	            }
    			}						
    			br.close();//关闭缓冲区		
    			return num;//返回单词数
    		}	
    

    3.统计文件的有效行数(对应输出第三行):任何包含非空白字符的行,都需要统计

    • 思路:行数统计直接按行读取后使用trim()函数去掉空白字符后,再对行数进行判断
    • 独到之处:使用了trim()函数去掉了字符串首尾的空格
    public static int lineNum(String filename) throws IOException  {
    	 		//统计行数
    			int num = 0;			
    			BufferedReader br = new BufferedReader(new FileReader(filename));
    			String line = null;
    			while ((line  = br.readLine()) != null) {
    				if (line.trim().length() != 0) {//使用trim()函数去掉字符串首尾的空格
    					num ++;					
    				}
    			}
    			br.close();		
    			return num;
    		}	
    

    4.统计文件中各单词的出现次数(对应输出接下来10行),最终只输出频率最高的10个

    • 思路:正则表达式判断匹配单词,匹配成功则计数(具体可见注释部分)
    • 独到之处:单词-次数作为键值对保存在TreeMap中,运用toLowerCase()方法将字符串数组中的元素转换成小写
    public static TreeMap<String, Integer> wordMap(String filename) throws IOException {
    	        TreeMap<String, Integer> tm = new TreeMap<String, Integer>();				
    			BufferedReader br = new BufferedReader(new FileReader(filename));
    			String separator = "[^A-Za-z0-9]";//分隔符
    			String regex = "^[A-Za-z]{4,}[0-9]*$"; // 正则判断每个数组中是否存在有效单词
    			Pattern p = Pattern.compile(regex);//使用Pattern.compile方法编译一个正则表达式,创建一个匹配模式
    			String str = null;
    			Matcher m = null;
    			String line = null;
    			String[] array = null;
    			while ((line  = br.readLine()) != null) {
    	            line = line.replaceAll("[(\u4e00-\u9fa5)]", "");// 过滤汉字
    	            line = line.replaceAll(separator, " "); // 用空格替换分隔符
    	            array = line.split("\s+"); // 按空格分割                     
    	            for (int i = 0;i<array.length;i++) { 
    	            	m = p.matcher(array[i]);//
    	            	if (m.matches()) {//如果正确匹配
    	            		str = array[i].toLowerCase();//运用toLowerCase()方法将字符串数组中的元素转换成小写                
    	                    if (!tm.containsKey(str)) {//用containsKey()方法看对应单词是否大小写重复
    	                        tm.put(str, 1);//输出对应单词小写
    	                    } else {
    	                        int count = tm.get(str) + 1;//单词没有重复则单词出现次数+1
    	                        tm.put(str, count);//输出对应单词小写和单词出现的次数
    	                    }
    	            	}
    	            }
    			}						
    			br.close();		
    			return tm;
    		}
    

    5.对单词进行排序并输出

    • 思路:以单词-频率作为键值对保存在TreeMap中,TreeMap会根据键的字典序自动升序排列,按照频率优先的顺序输出频率最高的10个单词(具体可见注释部分)
    • 独到之处:以单词-频率作为键值对保存在TreeMap中,TreeMap会根据键的字典序自动升序排列
    public static void writeMostWord(String infilename,String outfilename) throws IOException {//按照格式输出结果
    		String outpath = new File(outfilename).getAbsolutePath();
            FileWriter fw = new FileWriter(outpath, true);
            TreeMap<String, Integer> tm = wordMap(infilename);
    		if(tm != null && tm.size()>=1)
    		{		  
    			List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(tm.entrySet());
    			// 通过比较器来实现排序
    			Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
    				public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
    					//treemap默认按照键的字典序升序排列的,所以list也是排过序的,在值相同的情况下不用再给键升序排列		
    					// 按照值降序排序 
    					return o2.getValue().compareTo(o1.getValue());
    				}
    			});   
    			int i = 1;
    			String key = null;
    			Integer value = null;
    			for (Map.Entry<String, Integer> mapping : list) {
    				key = mapping.getKey();
    				value = mapping.getValue();
    				System.out.print("<" + key + ">: " + value + '
    ');
    				fw.write("<" + key + ">: " + value + '
    ');
    				//只输出前10个
    				if (i == 10) {
    					break;
    				}
    				i++;
    			}
    		}
    		fw.close();
    	}
    

    6.测试程序

    • input文件
    • output文件
    • 运行结果

    心路历程与收获

    第一眼看到这个作业就蒙了,因为作业描述实在太多了,本能排斥这次作业,就一直拖着,看着离ddl越来越近,在接近只有八天的时候,我坐不住了,就开始着手完成这次作业,查了大量资料,虽然这次作业真的很困难,但感觉自己真的学到了很多,复习了Java语言,学到了很多新的方法,正则表达式的作用太大了,pattern类和matcher类方法很有妙用,经过这次作业,也让我感觉到自身实力的不足,还得多加努力才行.

  • 相关阅读:
    sql 表连接
    easyui datagrid 列的内容超出所定义的列宽时,自动换行
    MySQL中函数CONCAT及GROUP_CONCAT
    第6章 Selenium2-Java 自动化测试模型
    第4章 Selenium2-java WebDriver API (三)
    第4章 Selenium2-java WebDriver API (二)
    第4章 Selenium2-java WebDriver API (一)
    第2章 Selenium2-java 测试环境搭建
    jsp导入外部样式
    第一章 Slenium2-Java 自动化测试基础
  • 原文地址:https://www.cnblogs.com/buxiu888/p/14607053.html
Copyright © 2011-2022 走看看