要求如下:
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 }