要求如下:
1.将哈利波特英文电子版导入,并统计每个英文字母出现概率(区分大小写),由大到小排序
2.统计该txt 文件中每个单词的个数,并按照要求输出频率最高的几个单词数目 和出现概率
功能1:
输出文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列。
功能2:
指定目录,对目录下的每一个文件执行功能1 操作
功能3:
指定文件目录,但是会递归目录下的所有子目录,每个文件执行功能1的操作。
问题:
1.程序如何识别每一个单词: 当出现非字母符号时划分为一个单词,用正则表达式来分割句子, 形成单词;
1 //非单词用来分割单词 2 String [] words = str.split("[^(a-zA-Z)]+");
2.如何存储单词和后边的数据:使用Map 数组, key值设置为 String 存储单词 ,value 根据需要改变类型
1 //创建哈希表 记录数目 2 Map<String,Integer> map =new HashMap<String,Integer>();
主要思想:
读取文件内的数据,将数据转换为char类型,区分大小写统计字母个数,于此同时统计字母总个数。
1.使用BufferedReader 读取的缓存流进行读取,将数据添加到字符串缓冲区 StringBuffer 当中,将字符串缓冲区中的数据转换为char类型进行存储,进行一个循环遍历,用Character.isLetter() 方法判断是否是字母,进而用Character.isLowerCase()判断是否是小写字母,用数组存储每个字母的出现次数,数组下标 如果是小写字母,则数组下标为 该字符(a-'a')(使用ASCII码表) 下标为0-25的存储小写字母,0-26存储大写字母,大写字母下标表示方法: a-'A'+26 ;
重新定义一个double 数组,长度为52,按顺序存储每个单词出现的频率百分比。 创建一个map 数组,key 存储 英文字母, value 存储 频率百分比。 定义一个list集合,里面存储Map类型 ,调用 Collections.sort()方法 进行 排序 ,遍历List 集合输出
key与value的 值。
2.将录入的单词首先存到String数组当中,然后遍历String 数组,如果没有该单词的存储就创建一个map存储,如果已有该单词value+1,于此同时赋值number为单词总个数.
遍历完成,针对 map数组的value 值进行排序,最后按要求输出出现次数频率最高的几个单词,以及根据要求输出的出现概率。
功能1:
调用要求2的数据,自定义一个 hashtable的排序方法(哈哈,本人目前还没有搞明白。。。。),按照功能进行排序
功能2:
用file的isFile 判断是路径指向是否是文件,如果是文件则执行功能1,如果不是则将该目录下的文件存储到File 类型数组,进行遍历并执行功能1.
功能3;
与功能2类似,如果路径指向目录,则遍历目录,如果遇到目录则继续遍历,不是就执行功能1.
源码如下:
1 package com.FileReaderWriter; 2 3 4 import java.io.BufferedReader; 5 import java.io.File; 6 import java.io.FileNotFoundException; 7 import java.io.FileReader; 8 import java.io.IOException; 9 import java.nio.charset.Charset; 10 import java.util.ArrayList; 11 import java.util.Collections; 12 import java.util.Comparator; 13 import java.util.HashMap; 14 import java.util.Hashtable; 15 import java.util.List; 16 import java.util.Map; 17 import java.util.Scanner; 18 19 /** 20 * 信1805-2 21 * 读取小说 并排序字母出现概率 22 * @author cuixingyu 23 * 按要求输出出现频率最高的单词和概率 24 */ 25 public class FileReaderWriter { 26 27 //查找单词并按要求输出 28 public static void word(String c) throws Exception { 29 30 File file =new File(c); 31 //导入路径 32 FileReader fr=new FileReader(file); 33 //带缓冲的输出流 34 BufferedReader br=new BufferedReader(fr); 35 //构造一个没有字符的字符串缓冲区,初始容量为16个字符 36 StringBuffer sb= new StringBuffer(); 37 String text=null; 38 //将读入的一行信息存储到text 中 39 while((text=br.readLine())!=null) { 40 //将读取出的字符text追加到StringBuffer 的 sb流中 41 sb.append(text); 42 } 43 //关闭读入流 44 br.close(); 45 46 //将sb缓存流中的所有单词转换为String 类型 然后变为小写 47 String str = sb.toString().toLowerCase(); 48 //非单词用来分割单词 49 String [] words = str.split("[^(a-zA-Z)]+"); 50 //创建哈希表 记录数目 51 Map<String,Integer> map =new HashMap<String,Integer>(); 52 // forreach 语句,均可转换为for循环语句 for(元素类型 元素变量 x:遍历对象obj) 53 double number=0; 54 double k=0; 55 for(String word :words){ 56 if(map.get(word)==null){ // 若不存在说明是第一次,则加入到map,出现次数为1 57 map.put(word,1); 58 number++; 59 k++; 60 }else{ 61 map.put(word,map.get(word)+1); // 若存在,次数累加1 62 number++; 63 } 64 } 65 66 //排序 67 //使用list集合 定义一个数组类型 list集合里放Map类型 每个Map的key 为String类型 对应的value为Integer 类型 68 //map.entrySet() 返回此地图中包含的映射的Set视图。 ?? 69 List<Map.Entry<String ,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(map.entrySet()); 70 71 Comparator<Map.Entry<String,Integer>> comparator = new Comparator<Map.Entry<String, Integer>>() { 72 public int compare(Map.Entry<String, Integer> left, Map.Entry<String, Integer> right) 73 { 74 return (left.getValue().compareTo(right.getValue())); 75 } 76 }; 77 78 //排序方法 默认为 升序 79 80 81 Collections.sort(list,comparator); 82 System.out.println("单词总个数:"+number); 83 System.out.println("不相同单词个数:"+k); 84 System.out.println("请输入要查询的位数N:"); 85 Scanner sc=new Scanner(System.in); 86 int n=sc.nextInt(); 87 for(int j=0;j<n;j++) { 88 double b=(list.get(list.size()-j-1).getValue()/number)*100; 89 System.out.println(list.get(list.size()-j-1).getKey() +":"+list.get(list.size()-j-1).getValue()+" "+String.format("%.2f", b)+"%"); //输出结果 90 } 91 92 93 //找寻文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列 94 Hashtable<String,Integer> hashtable=new Hashtable<String,Integer>(); 95 96 for(String word :words){ 97 // 若不存在说明是第一次,则加入到map,出现次数为1 98 if(hashtable.get(word)==null){ 99 hashtable.put(word,1); 100 }else{ 101 // 若存在,次数累加1 102 hashtable.put(word,hashtable.get(word)+1); 103 } 104 } 105 //把哈希表排序 106 mapValueSort((Hashtable<String,Integer>)hashtable); //把哈希表排序 107 } 108 //自定义哈希排序 输出按照个数 字母表排序 109 private static void mapValueSort(Hashtable<String, Integer> hashtable) { 110 // TODO Auto-generated method stub 111 List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(hashtable.entrySet());//创建集合list,并规范集合为哈希表类型,并用hashtable.entrySet()初始化 112 //定义list排序函数 113 list.sort(new Comparator<Map.Entry<String, Integer>>() 114 { 115 public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) 116 { 117 //比较两者之间字典序大小并其值赋给变量a 118 int a=o1.getKey().compareTo(o2.getKey()); 119 //比较两者之间次数的大小 120 if(o1.getValue() < o2.getValue()) 121 { 122 return 1; //若后者大返回1,比较器会将两者调换次序,此为降序 123 } 124 else if((o1.getValue() == o2.getValue())||((o1.getValue()==1)&&(o2.getValue()==1))) //若次数相同比较字典序 125 { 126 if(a!=0&&a>0) //字典序在前的在前面 127 { 128 return 1; 129 } 130 } 131 return -1; 132 } 133 }); 134 int k=0; 135 double sum=0; 136 for (Map.Entry<String, Integer> mapping :list) //遍历排序后的集合 137 { 138 139 sum+=mapping.getValue(); 140 } 141 142 System.out.println("功能1:输出文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列"); 143 for (Map.Entry<String, Integer> mapping :list) //遍历排序后的集合 144 { 145 System.out.println(mapping.getKey() + ":" + mapping.getValue()); 146 } 147 148 } 149 //查找字母并按要求输出。 150 public void character(String c) throws Exception { 151 //导入路径 152 FileReader fr=new FileReader(c); 153 //带缓冲的输出流 154 BufferedReader br=new BufferedReader(fr); 155 //构造一个没有字符的字符串缓冲区,初始容量为16个字符 156 StringBuffer sb= new StringBuffer(); 157 String text=null; 158 //将读入的一行信息存储到text 中 159 while((text=br.readLine())!=null) { 160 //将读取出的字符text追加到StringBuffer 的 sb流中 161 sb.append(text); 162 } 163 //关闭读入流 164 br.close(); 165 166 //将字符串转换为单个的字符 167 char[] str=sb.toString().toCharArray(); 168 169 //统计单词个数 170 double number=0; 171 //计数数组 172 int []count=new int [52]; 173 174 for(int i=0;i<str.length;i++) { 175 //判断该字符是否时字母 176 if(Character.isLetter(str[i])) { 177 //判断是否时小写字母 178 if(Character.isLowerCase(str[i])) 179 { 180 count[str[i]-'a']++; 181 number++; 182 }else { 183 count[str[i]-'A'+26]++; 184 number++; 185 } 186 } 187 } 188 189 //计算概率 190 double []s=new double [52] ; 191 for(int k=0;k<52;k++) { 192 //化为百分比 193 s[k]=count[k]/number*100; 194 } 195 //定义哈希表 196 Map<String,Double> map =new HashMap<String,Double>(); 197 198 for(int i=0;i<s.length;i++) { 199 200 //哈希表 前一个记录字母,后一个记录概率 201 if(i<26) { 202 //小写字母统计 203 char q=(char)(i+97); 204 String key=String.valueOf(q); 205 map.put(key, s[i]); 206 }else { 207 //大写字母统计 208 char q=(char)(i+65-26); 209 String key=String.valueOf(q); 210 map.put(key, s[i]); 211 } 212 } 213 214 215 //排序 默认为升序 216 217 List<Map.Entry<String,Double>> list = new ArrayList<Map.Entry<String,Double>>(map.entrySet()); 218 219 Comparator<Map.Entry<String,Double>> comparator = new Comparator<Map.Entry<String,Double>>() { 220 public int compare(Map.Entry<String,Double> left, Map.Entry<String,Double> right) 221 { 222 return (left.getValue().compareTo(right.getValue())); 223 } 224 }; 225 226 227 Collections.sort(list,comparator); 228 229 for(int j=0;j<s.length;j++) { 230 System.out.println(list.get(list.size()-j-1).getKey() +":"+String.format("%.2f", list.get(list.size()-j-1).getValue())+"%"); //输出结果 231 } 232 233 } 234 235 //递归遍历目录下的所有子目录 236 @SuppressWarnings("null") 237 static void getPath(String a) throws Exception { 238 FileReaderWriter test1=null; 239 File file = new File(a); 240 241 File []array =file.listFiles(); 242 for(int i=0;i<array.length;i++) { 243 //判断是否是目录 244 if(array[i].isDirectory()) { 245 getPath(array[i].getPath()); 246 }else { 247 word(array[i].getPath()); 248 } 249 } 250 } 251 252 253 public static void main(String[] args) throws Exception { 254 FileReaderWriter test= new FileReaderWriter(); 255 String c="C://Users//cuixingyu//Desktop//Harry Potter and the Sorcerer's Stone.txt"; 256 String b="D://cxy//454"; 257 System.out.println("输出某个英文文本文件中 26 字母出现的频率,由高到低排列,并显示字母出现的百分比,精确到小数点后面两位:"); 258 test.character(c); 259 260 261 262 /*File file = new File(c); 263 if(file.isFile()) { 264 System.out.println("功能1:输出文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列"); 265 test.word(c); 266 } 267 //指定文件目录,对目录下每一个文件执行 功能1的操作 268 else { 269 File []array =file.listFiles(); 270 for(int i=0;i<array.length;i++) { 271 //判断是否是目录 272 if(!array[i].isDirectory()) { 273 System.out.println("功能1:输出文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列"); 274 test.word(array[i].getPath()); 275 } 276 } 277 278 }*/ 279 280 //递归遍历所给目录中的所有子目录,并进行功能1 操作 281 File file = new File(b); 282 if(file.isFile()) { 283 System.out.println("功能1:输出文件中所有不重复的单词,按照出现次数由多到少排列,出现次数同样多的,以字典序排列"); 284 test.word(b); 285 } 286 else { 287 getPath(b); 288 } 289 } 290 }