Java文本处理12-找出文本最长句与最短句并计算方差

1、任务简介

在分句完成后我们可以统计出每一个句子的长度(指句子包含的汉字数),在此基础上我们可以找出最长的句子和最短的句子,并且可以计算出句子长度的方差,本节任务的第一个程序是将结果打印出来,第二个程序是将结果保存到一个指定文本文档中。


2、基本任务和代码

(1)任务1

1)任务内容

找出文本的最长句和最短句,并计算出文本的句长方差,将结果打印到黑屏幕上。

2)具体思路

(1)首先需要使用InputStreamReader类和BufferedReader类实现文本的读取,由于我使用的文本文档均为utf-8编码,所以还需要指定编码格式为utf-8;

(2)然后需要定义一个空的字符串变量,在对文本逐行读出后将读出的内容追加到该空字符串后;

(3)定义一个TreeMap集合并通过该集合排序,由于我们需要找出最长句和最短句,所以可以通过TreeMap中的Key值进行排序,并且将集合定义为TreeMap的形式,使其Key对应句子的汉字数,由于Key默认是升序排序,所以可以使用lastKey()方法可以获取一个最高键(对应汉字数最多的句子),也就是最长的句子,再使用firstKey()方法获取最短的句子;

(4)逐行读出文档,然后使用for循环对该行中的每一个字符进行遍历,使用toString()方法得到每一个字符,再使用if语句和matches()方法检测字符是否为汉字,若匹配则对指定的变量进行自增,求出每一句的汉字数和总的汉字数;

(5)再使用if语句和equals()方法字符是否为“。” “!”和“?”三种符号之一,若为其中之一则句子数+1,并且需要将该句的汉字数和内容添加到TreeMap集合中,再将统计变量重置从而满足下一句的循环统计,其中我还注释了输出语句,该语句可以用于输出读取到的每一句话及其长度,有需要时可以取消注释;

(6)使用总汉字数\总句子数就可以得到该文本中每一句话的平均句长,得到该值是求方差的基础,方差计算公式如下:
在这里插入图片描述
式中M为平均句长,x表示每一句话的长度,n为总句子数;

(7)最后使用keySet()方法获取TreeMap集合的键值对,获取其Key值即为每一句的长度,分别用每一句的长度减去平均长度后取平方相加,再用累加后的结果除以总句子数即为句长方差;

3)任务代码

程序保存为juzi5.java,代码如下:

import java.io.*;//导入java.io包中的所有类
import java.util.*;//导入java.util包中的所有类
public class juzi5 {//类名
    public static void main(String[] args)  {//程序主函数
        try {//try代码块,当发生异常时会转到catch代码块中
        	//读取指定的文件
        	Scanner s1 = new Scanner(System.in);//创建scanner,控制台会一直等待输入,直到敲回车结束
        	System.out.println("请输入想要打开的文本文档:");//输入提示信息
        	String a1 = s1.nextLine();//定义字符串变量,并赋值为用户输入的信息
        	//创建类进行文件的读取,并指定编码格式为utf-8
        	InputStreamReader read = new InputStreamReader(new FileInputStream(a1),"utf-8"); 
            BufferedReader in = new BufferedReader(read);//可用于读取指定文件     
			StringBuffer b = new StringBuffer();//定义一个字符串变量,便于后续进行内容追加的操作
			String str = null;//定义一个字符串类型变量
			String d = null;//定义一个字符串类型变量
			String g = "";//定义一个字符串类型变量
			double e = 0;//定义一个double型变量,用于统计总句子数
			double c1 = 0;//定义一个double型变量,用于统计总汉字数
			int c2 = 0;//定义一个int型变量,用于统计每一句包含的汉字数
			TreeMap<Integer,String> tm=new TreeMap<Integer,String>();//定义一个TreeMap集合
			while((str = in.readLine()) != null) {//readLine()方法, 用于读取一行,只要读取内容不为空就一直执行
				b.append(str);//将该行内容追加到字符串b的后面
				for (int j = 0; j < str.length(); j++) {//for循环的条件,当j小于该行长度时就一直循环并自增
            		d = Character.toString(str.charAt(j));//返回一个字符串对象
            		g += d;//连接两个字符串
            		if (d.matches("[\\u4e00-\\u9fa5]")) {//if语句的条件,判断是否为汉字
                        c1++;//若为汉字则c1自增
                        c2++;//若为汉字则c2自增
                    }
            		if (d.equals("。")||d.equals("?")||d.equals("!")) {//if语句的条件,判断是否为句子
                        e++;//若为一句则e自增一次
//                        System.out.print("第"+(int)e+"句话:  "+g+"  本句包含"+c2+"个汉字"+"\n");//输出结果
                        tm.put(c2,g);//在TreeMap中添加值
                        c2 = 0;//重置统计变量
                        g = "";//重置统计变量
                    }
			    }
			}
			//利用Key值默认的升序排序输出最高键和最低键对应的句子即为最长句和最短句
			System.out.println("文本中最长的句子为:"+tm.get(tm.lastKey())+" 汉字:"+tm.lastKey()+"个");//输出最长句
			System.out.println("文本中最短的句子为:"+tm.get(tm.firstKey())+" 汉字:"+tm.firstKey()+"个");//输出最短句
            in.close();//关闭流 
            double f = c1/e;//计算文本平均句长
            double h = 0;//定义一个double型变量
            Iterator<Integer>it = tm.keySet().iterator();//获取tm的key值并迭代
            while (it.hasNext()) {//检查序列中是否含有元素,若有则为true
            	int key = it.next();//定义变量获取元素
            	h += (key-f)*(key-f);//计算方差的中间步骤        	
            }
            double fangcha = h/e;//求得方差
            System.out.println("该文本方差为"+fangcha);//输出方差
            System.out.println("该文本共有"+(int)e+"个句子");//输出总的句子数
            System.out.println("该文本共有"+(int)c1+"个汉字");//输出总的汉字数
            System.out.println("该文本平均句长为"+f);//输出平均句长
        } catch (IOException e) {//当try代码块有异常时转到catch代码块
        	e.printStackTrace();//printStackTrace()方法是打印异常信息在程序中出错的位置及原因
        }
    }
}

4)运行结果

(1)所有文件均保存在路径D:\demo8下,对一个格式为utf-8的简单文本进行操作,该文本文档命名为 lsy.txt,内容如下:
Java文本处理12-找出文本最长句与最短句并计算方差_第1张图片
在命令行中对程序进行编译,并运行程序读取该txt文档,计算结果如下:
Java文本处理12-找出文本最长句与最短句并计算方差_第2张图片
我通过自己运算的句长方差也为6.6875,具体计算如下:
Java文本处理12-找出文本最长句与最短句并计算方差_第3张图片

由此也证明该程序计算方差的准确性。

(2)在命令行下使用该程序对原版《西游记》txt文档进行计算,计算结果如下:
Java文本处理12-找出文本最长句与最短句并计算方差_第4张图片
文中最短的句子没有汉字,我认为是我使用的原版《西游记》是从网上下载的,由于资源的不规范所以“。” “!”和“?”三种符号中的两个符号连在了一起,造成了最短句子没有汉字。


(2)任务2

1)任务内容

找出文本的最长句和最短句,并计算出文本的句长方差,并将结果输出到一个指定的文本文档中(将任务1的输出内容保存到指定文本文档中)。

2)具体思路

(1)首先在任务1的基础上加上一个Scanner类,用于读取用户想要存入的文档路径和文档名;

(2)然后使用PrintStream类直接打印输出流,将内容保存到指定路径即可;

3)任务代码

程序保存为juzi6.java,代码如下:

import java.io.*;//导入java.io包中的所有类
import java.util.*;//导入java.util包中的所有类
public class juzi6 {//类名
    public static void main(String[] args)  {//程序主函数
        try {//try代码块,当发生异常时会转到catch代码块中
        	//读取指定的文件
        	Scanner s1 = new Scanner(System.in);//创建scanner,控制台会一直等待输入,直到敲回车结束
        	Scanner s2 = new Scanner(System.in);//创建scanner,控制台会一直等待输入,直到敲回车结束
        	System.out.println("请输入想要打开的文本文档:");//输入提示信息
        	String a1 = s1.nextLine();//定义字符串变量,并赋值为用户输入的信息
        	System.out.println("请输入想要写入内容的文本文档:");//输入提示信息
        	String a2 = s2.nextLine();//定义字符串变量,并赋值为用户输入的信息
        	File file=new File(a2);//用命令行参数直接写入待写入文件	
			if(!file.exists()) {//if语句的条件,若指定路径下该文件不存在
	            file.createNewFile();//则在指定路径下新建该文件
	            }
        	//创建类进行文件的读取,并指定编码格式为utf-8
        	InputStreamReader read = new InputStreamReader(new FileInputStream(a1),"utf-8"); 
            BufferedReader in = new BufferedReader(read);//可用于读取指定文件     
			StringBuffer b = new StringBuffer();//定义一个字符串变量,便于后续进行内容追加的操作
			String str = null;//定义一个字符串类型变量
			String d = null;//定义一个字符串类型变量
			String g = "";//定义一个字符串类型变量
			double e = 0;//定义一个double型变量,用于统计总句子数
			double c1 = 0;//定义一个double型变量,用于统计总汉字数
			int c2 = 0;//定义一个int型变量,用于统计每一句包含的汉字数
			TreeMap<Integer,String> tm=new TreeMap<Integer,String>();//定义一个TreeMap集合
			PrintStream out = new PrintStream(file);//打印输出流,并指定保存路径
            System.setOut(out);//改变输出流并将内容保存到指定路径
			while((str = in.readLine()) != null) {//readLine()方法, 用于读取一行,只要读取内容不为空就一直执行
				b.append(str);//将该行内容追加到字符串b的后面
				for (int j = 0; j < str.length(); j++) {//for循环的条件,当j小于该行长度时就一直循环并自增
            		d = Character.toString(str.charAt(j));//返回一个字符串对象
            		g += d;//连接两个字符串
            		if (d.matches("[\\u4e00-\\u9fa5]")) {//if语句的条件,判断是否为汉字
                        c1++;//若为汉字则c1自增
                        c2++;//若为汉字则c2自增
                    }
            		if (d.equals("。")||d.equals("?")||d.equals("!")) {//if语句的条件,判断是否为句子
                        e++;//若为一句则e自增一次
//                        System.out.print("第"+(int)e+"句话:  "+g+"  本句包含"+c2+"个汉字"+"\n");//输出结果
                        tm.put(c2,g);//在TreeMap中添加值
                        c2 = 0;//重置统计变量
                        g = "";//重置统计变量
                    }
			    }
			}
			//利用Key值默认的升序排序输出最高键和最低键对应的句子即为最长句和最短句
			System.out.println("文本中最长的句子为:"+tm.get(tm.lastKey())+" 汉字:"+tm.lastKey()+"个");//输出最长句
			System.out.println("文本中最短的句子为:"+tm.get(tm.firstKey())+" 汉字:"+tm.firstKey()+"个");//输出最短句
            in.close();//关闭流 
            double f = c1/e;//计算文本平均句长
            double h = 0;//定义一个double型变量
            Iterator<Integer>it = tm.keySet().iterator();//获取tm的key值并迭代
            while (it.hasNext()) {//检查序列中是否含有元素,若有则为true
            	int key = it.next();//定义变量获取元素
            	h += (key-f)*(key-f);//计算方差的中间步骤        	
            }
            double fangcha = h/e;//求得方差
            System.out.println("该文本方差为"+fangcha);//输出方差
            System.out.println("该文本共有"+(int)e+"个句子");//输出总的句子数
            System.out.println("该文本共有"+(int)c1+"个汉字");//输出总的汉字数
            System.out.println("该文本平均句长为"+f);//输出平均句长
        } catch (IOException e) {//当try代码块有异常时转到catch代码块
        	e.printStackTrace();//printStackTrace()方法是打印异常信息在程序中出错的位置及原因
        }
    }
}

4)运行结果

(1)所有文件均保存在路径D:\demo8下,在命令行中对程序进行编译,然后读取路径下的《西游记》文档xyj.txt,然后将内容保存到该路径下的xieru4.txt文档中,命令行操作如下:
Java文本处理12-找出文本最长句与最短句并计算方差_第5张图片
(2)打开路径D:\demo8下的xieru4.txt文档,部分内容显示如下:
Java文本处理12-找出文本最长句与最短句并计算方差_第6张图片
此时已经将任务1中打印到黑屏幕上的内容写入了一个指定的文本文档中。


3、总结

通过该程序可以找出文本中的最长句和最短句,并且可以计算出文本的句长方差,但是由于使用的《西游记》中“。” “!”和“?”三种符号中的两个符号连在了一起,造成了最短句子没有汉字。在使用简单文本测试时计算的方差结果是正确的,但是由于没有对比,所以不知道计算出的《西游记》文本句长方差是否有错误,故文中的错误还请读者指正,博主对此感激不尽。

你可能感兴趣的:(Java)