中英文字数统计以及信息熵的计算
一、实验要求
- 使用Java对任意一部中英文小说进行字符统计,中文小说统计各个中文字符使用的频率,并且计算出中文小说西游记中共使用了多少个汉字。
- 英文小说统计26个英文字母的使用频率。
- 计算中文小说西游记的各个汉字的信息熵。
- 计算英文小说26个英文字母各自的信息熵。
二、功能实现
2.1实验环境
- java 1.8.0._171
- idea 2017.2
2.2统计中文小说的使用频率
2.2.1代码部分
package main.java.demo;
/**
* Created with IntelliJ IDEA.
* User: kingback
* Author:king@王延凯
* Date: 2019/7/5
* Time: 23:28
* Description: No Description
*/
import java.io.*;//导入java.io包中的所有类
import java.util.*;//导入java.util包中的所有类
public class Journey_to_West {
public static void main(String[] args) {
try {//try代码块,当发生异常时会转到catch代码块中
//所要查询的中文txt文件路径
String input="C:\\Users\\kingback\\Desktop\\龙华老师资料\\上交资料\\第九次上交材料\\西游记\\西游记中文版.txt";
//创建类进行文件的读取,并指定编码格式为utf-8
InputStreamReader read = new InputStreamReader(new FileInputStream(input),"GBK");
BufferedReader in = new BufferedReader(read);//可用于读取指定文件
StringBuffer b = new StringBuffer();//定义一个字符串变量b,便于后续进行内容追加的操作
String str = null;//定义一个字符串类型变量str
int i = 0;//定义一个整型变量,用于统计字符串的出现次数
while((str = in.readLine()) != null) {//readLine()方法, 用于读取一行,只要读取内容不为空就一直执行
b.append(str);//将该行内容追加到字符串b的后面
}
TreeMap<Character,Integer>tm =Pross(b.toString());//调用TreeMap函数
List<Map.Entry<Character,Integer>> list = new ArrayList<Map.Entry<Character,Integer>>(tm.entrySet());//将map转换为list便于进行排序
/* 写入Txt文件 */
//所要存储结果的文件路径
File writename = new File("C:\\Users\\kingback\\Desktop\\龙华老师资料\\上交资料\\第九次上交材料\\西游记\\result.txt"); // 相对路径,如果没有则要建立一个新的output。txt文件
writename.createNewFile(); // 创建新文件
BufferedWriter out = new BufferedWriter(new FileWriter(writename));
String hh=tm.toString();
String[] sourceStrArray = hh.split("\\,|\\{|\\}");//分割出来的字符数组,多字符分割
for (int ii = 0; ii < sourceStrArray.length; ii++) {
System.out.println(sourceStrArray[ii]);//屏幕输出,查看结果
out.write(sourceStrArray[ii]+"\n");//写入txt文件
out.flush(); // 把缓存区内容压入文件
}
out.close(); // 最后记得关闭文件
Iterator<Integer>it = tm.values().iterator();//获取tm中value值并迭代
while(it.hasNext()) {//检查序列中是否含有元素,若有则为true
Integer j=(Integer)it.next();//定义变量获取元素
i+=j;//迭代求总字符数
}
in.close();//关闭流
System.out.println("总汉字数为"+i);//输出总的汉字数
} catch (IOException e) {//当try代码块有异常时转到catch代码块
e.printStackTrace();//printStackTrace()方法是打印异常信息在程序中出错的位置及原因
}
}
public static TreeMap<Character,Integer>Pross(String str) {//构造TreeMap统计方法
String d = null;//定义一个字符串类型变量
char[] charArray = str.toCharArray();//将字符串转换为字符数组
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();//定义一个TreeMap集合
for(int x = 0;x < charArray.length;x++) {//循环遍历字符数组
d=Character.toString(charArray[x]);//返回一个字符串对象
if (d.matches("[\\u4e00-\\u9fa5]")) {//if语句的条件,判断是否为汉字
if(!tm.containsKey(charArray[x])) {//if语句的条件,判断该汉字是否在tem中
tm.put(charArray[x], 1);//若该汉字不在tem中则初始化其value值为1
} else {//若该汉字在tem中
int count = tm.get(charArray[x])+1;//其出现次数增加1
tm.put(charArray[x],count);//若汉字在tem中则其value值为count
}
}
}
return tm;//返回
}
}
2.2.2运行结果
2.3统计英文小说26个英文字母的使用频率
2.3.1代码部分
package main.java.demo;
/**
* Created with IntelliJ IDEA.
* User: kingback
* Author:king@王延凯
* Date: 2019/7/6
* Time: 9:49
* Description: No Description
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
public class Jane_Eyre {
public static void main(String[] args) {
/*
* 该程序主要完成从硬盘上读取一个文件里的内容,然后统计26个英文字母分别出现的频率
* 首先需要读取我们存放在桌面的英文小说Jane_Eyre.txt文件,里面限定只能输入小写的字母,接着运行程序即可看到结果
*/
String Filename="C:\\Users\\kingback\\Desktop\\龙华老师资料\\上交资料\\第九次上交材料\\简爱英文版\\Jane_Eyre_048\\Jane Eyre - Charlotte Bronte.txt";
File file = new File(Filename);
InputStream ips = null;
ArrayList<Integer> arr = new ArrayList<Integer>();
char[] lower = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z' };//存放26个英文字母
try {
//System.out.println("以字节为单位读取文件内容,一次读一个字节:");
ips = new FileInputStream(file);
int tempbyte;
while ((tempbyte = ips.read()) != -1) {
arr.add(tempbyte);
}
ips.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
System.out.println("从文件读出的内容,按照从a到z的字母出现频率如下:");
int nums=0;
for(int arr1:tongjipinlv(arr,lower)){
System.out.print(arr1+",");
nums+=arr1;
}
System.out.println("\n该小说中所有小写字母的个数为:"+nums);
int[] result=tongjipinlv(arr,lower);//用来获取英文字母的个数
//计算英文字母的信息熵
for (int i = 0; i < 26; i++) {
double p = (double)result[i]/nums;//定义一个double型变量,计算该汉字在文章中的出现概率
double H = -p * (Math.log(p) / Math.log(2));//定义一个double型变量,计算该汉字的信息熵
System.out.println("字母"+lower[i]+" "+"个数为:"+result[i]+" 信息熵为:"+H);
}
}
//统计字母出现频率
public static int[] tongjipinlv(ArrayList<Integer> arr,char[] lower) {
int[] count ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//遍历查询出结果
for (int i=0;i<lower.length;i++)
for(int j=0;j<arr.size();j++){
if (arr.get(j) == lower[i]) {
++count[i];
}
}
return count;//返回26个字母的结果
}
}
2.3.2运行结果
2.4计算中文小说西游记的各个汉字的信息熵
对于汉字信息熵的求解是在上边求出各个汉字的使用频率后继续进行的计算。以下为该计算实现的代码部分:
2.4.1代码部分
// 计算信息熵
// 根据数学公式来进行计算
for(Map.Entry<Character,Integer> mapping:list) {//遍历list
int f = mapping.getValue();
double p = (double)f/i;//定义一个double型变量,计算该汉字在文章中的出现概率
double H = -p * (Math.log(p) / Math.log(2));//定义一个double型变量,计算该汉字的信息熵
System.out.println(mapping.getKey()+":"+mapping.getValue()+" 信息熵为:"+H+"比特/符号"); //输出降序排序的结果
}
2.4.2运行结果
2.5计算英文小说26个字母各自的信息熵
2.5.1代码部分
int[] result=tongjipinlv(arr,lower);//用来获取英文字母的个数
//计算英文字母的信息熵
for (int i = 0; i < 26; i++) {
double p = (double)result[i]/nums;//定义一个double型变量,计算该汉字在文章中的出现概率
double H = -p * (Math.log(p) / Math.log(2));//定义一个double型变量,计算该汉字的信息熵
System.out.println("字母"+lower[i]+" "+"个数为:"+result[i]+" 信息熵为:"+H);
}
2.5.2运行结果
2.6 过程截图
2.6.1 英文字母的
2.6.2 中文小说的
2.7 实验总结
该实验主要考察了使用Java对于文本的写入和读取,以及对于信息熵概念的理解。最后说明一下,如果有人需要实验中所用到的《西游记》和《简爱》的txt版本,可以给我留言,看到必免费赠送。