IO流练习题综合大全
一、网络爬虫
1.1 爬取姓氏
假数据制造:
百家姓
男生的名字(没有姓氏)
题目:
做题思路:
- 通过网络爬取将所有的数据
- 将获取到的网页数据通过正则表达式获取到符合条件的数据
- 将获取到的所有数据都二次加工,获取成完整的名字
- 将数据添加到文件当中
通过网络爬取将所有的数据使用的方法
/*
* 参数:输入的网站地址
* 作用:获取到所有的名字姓氏
* 返回值:把所有的数据都拼接成一个字符串返回
*
* */
private static String webCrawler(String net) throws IOException {
//1 .创建StringBuilder来拼接获取到的数据
StringBuilder sb = new StringBuilder();
//2. 创建url对象
URL url = new URL(net);
//3. 将创建好的url对现象进行联网
//细节:就是在这个过程当中需要联网
URLConnection conn = url.openConnection();
//4. 读取数据
InputStreamReader isr = new InputStreamReader(conn.getInputStream());
int len;
while ((len = isr.read()) != -1){
sb.append((char) len);
}
//5. 释放资源
isr.close();
//6. 返回数据
return sb.toString();
}
==将获取到的网页数据通过正则表达式获取到符合条件的数据 ==
/*
* 作用:通过正则表达式,返回符合格式的数据信息
* 参数:
* 1. 获取到的数据
* 2. 正则表达式
* 3. 获取到正则表达式切割出来的数组的下标值
* */
private static ArrayList<String> getData(String str, String regex, int index) {
//创建集合将数据存储
ArrayList<String> list = new ArrayList<>();
//通过正则表达式,进行验证,将符合的数据添加到集合当中
Pattern pattern = Pattern.compile(regex);
//获取到的规则方法,到str去寻找符合的
Matcher matcher = pattern.matcher(str);
while (matcher.find()){
list.add(matcher.group(index));
}
return list;
}
将获取到的所有数据都二次加工,获取成完整的名字
/*
* 作用:获取到真正的名字格式
* 参数:
* 1. 姓氏的集合
* 2. 男生名字的集合
* 3. 女生名字的集合
* 4. 获取男生名字的个数
* 5.获取女生名字的个数
*
* */
public static ArrayList<String> getName(ArrayList<String> familyNameList,ArrayList<String> boyNameList,ArrayList<String> girlNameList,int boyCount,int girlCount) {
//5.1生成男生不重复的名字
HashSet<String> boyhs = new HashSet<>();
while (true) {
if (boyhs.size() == boyCount) {
break;
}
//获取到随机的名字
//将数组内容打乱,获取到第一个元素,就是打乱的数据
Collections.shuffle(familyNameList);
Collections.shuffle(boyNameList);
//拼接信息
boyhs.add(familyNameList.get(0) + boyNameList.get(0));
}
//5.2生成女生不重复的名字
HashSet<String> girlhs = new HashSet<>();
while (true) {
if (girlhs.size() == girlCount) {
break;
}
//获取到随机的名字
//将数组内容打乱,获取到第一个元素,就是打乱的数据
Collections.shuffle(familyNameList);
Collections.shuffle(girlNameList);
//拼接信息
girlhs.add(familyNameList.get(0) + girlNameList.get(0));
}
// 6 生成男生信息添加到集合当中
//创建集合存储数据
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
//年龄 18~27
for (String boyName : boyhs) {
int age = r.nextInt(10)+18;
list.add(boyName + "-"+"男-"+ age);
}
//6. 获取女生的信息放到集合当中
for (String girlName: girlhs) {
int age = r.nextInt(10)+16;//16~26
list.add(girlName+"-女-"+age);
}
return list;
}
将数据添加到文件当中
//添加数据到文件当中
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\Java文件夹\\words\\IOExrecise\\b.txt"));
for (String s : list) {
bw.write(s);
bw.newLine();
}
bw.close();
完整代码
package IOExerciseMoreMore.miotest2;
/*
* 通过网络爬取获得数据
* */
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test1 {
public static void main(String[] args) throws IOException {
//1. 定义变量记录网网址
String familyNameNet = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";
String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
//2.调用方法将所有的数据获取出来,拼接成字符串
String familyNameStr = webCrawler(familyNameNet);
String girlNameStr = webCrawler(girlNameNet);
String boyNameStr = webCrawler(boyNameNet);
//3.通过正则表达式,返回符合格式的数据信息
ArrayList<String> familyTempList = getData(familyNameStr, "(.{4})(,|。)", 1);
ArrayList<String> boyTempList = getData(boyNameStr, "([\\u4E00-\\u9FA5]{2})(、|。)", 1);
ArrayList<String> girlTempList = getData(girlNameStr, "(.. ){4}..", 0);
//4.创建新集合,将所有的数据处理完全
//4.1. 姓氏转化(四个四个为一的,将每一组取出来获取单个即可)
ArrayList<String> familyNameList = new ArrayList<>();
for (String s : familyTempList) {
for (int i = 0; i < s.length(); i++) {
//获取到每组的每个元素
char c = s.charAt(i);
familyNameList.add(c+"");
}
}
// 4.2. 男生名字转化
//去重
ArrayList<String> boyNameList = new ArrayList<>();
for (String s : boyTempList) {
if (! boyNameList.contains(s)){
boyNameList.add(s);
}
}
//4.3. 女生名字转化
//可以按照空格进行划分
ArrayList<String> girlNameList = new ArrayList<>();
for (String s : girlTempList) {
String[] arr = s.split(" ");
for (int i = 0; i < arr.length; i++) {
girlNameList.add(arr[i]);
}
}
//5. 生成数据
//姓名(唯一)-性别-年龄
ArrayList<String> list = getName(familyNameList, boyNameList, girlNameList, 15, 25);
//打乱 数据顺序
Collections.shuffle(list);
//添加数据到文件当中
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\Java文件夹\\words\\IOExrecise\\b.txt"));
for (String s : list) {
bw.write(s);
bw.newLine();
}
bw.close();
}
/*
* 作用:获取到真正的名字格式
* 参数:
* 1. 姓氏的集合
* 2. 男生名字的集合
* 3. 女生名字的集合
* 4. 获取男生名字的个数
* 5.获取女生名字的个数
*
* */
public static ArrayList<String> getName(ArrayList<String> familyNameList,ArrayList<String> boyNameList,ArrayList<String> girlNameList,int boyCount,int girlCount) {
//5.1生成男生不重复的名字
HashSet<String> boyhs = new HashSet<>();
while (true) {
if (boyhs.size() == boyCount) {
break;
}
//获取到随机的名字
//将数组内容打乱,获取到第一个元素,就是打乱的数据
Collections.shuffle(familyNameList);
Collections.shuffle(boyNameList);
//拼接信息
boyhs.add(familyNameList.get(0) + boyNameList.get(0));
}
//5.2生成女生不重复的名字
HashSet<String> girlhs = new HashSet<>();
while (true) {
if (girlhs.size() == girlCount) {
break;
}
//获取到随机的名字
//将数组内容打乱,获取到第一个元素,就是打乱的数据
Collections.shuffle(familyNameList);
Collections.shuffle(girlNameList);
//拼接信息
girlhs.add(familyNameList.get(0) + girlNameList.get(0));
}
// 6 生成男生信息添加到集合当中
//创建集合存储数据
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
//年龄 18~27
for (String boyName : boyhs) {
int age = r.nextInt(10)+18;
list.add(boyName + "-"+"男-"+ age);
}
//6. 获取女生的信息放到集合当中
for (String girlName: girlhs) {
int age = r.nextInt(10)+16;//16~26
list.add(girlName+"-女-"+age);
}
return list;
}
/*
* 作用:通过正则表达式,返回符合格式的数据信息
* 参数:
* 1. 获取到的数据
* 2. 正则表达式
* 3. 获取到正则表达式切割出来的数组的下标值
* */
private static ArrayList<String> getData(String str, String regex, int index) {
//创建集合将数据存储
ArrayList<String> list = new ArrayList<>();
//通过正则表达式,进行验证,将符合的数据添加到集合当中
Pattern pattern = Pattern.compile(regex);
//获取到的规则方法,到str去寻找符合的
Matcher matcher = pattern.matcher(str);
while (matcher.find()){
list.add(matcher.group(index));
}
return list;
}
/*
* 参数:输入的网站地址
* 作用:获取到所有的名字姓氏
* 返回值:把所有的数据都拼接成一个字符串返回
*
* */
private static String webCrawler(String net) throws IOException {
//1 .创建StringBuilder来拼接获取到的数据
StringBuilder sb = new StringBuilder();
//2. 创建url对象
URL url = new URL(net);
//3. 将创建好的url对现象进行联网
//细节:就是在这个过程当中需要联网
URLConnection conn = url.openConnection();
//4. 读取数据
InputStreamReader isr = new InputStreamReader(conn.getInputStream());
int len;
while ((len = isr.read()) != -1){
sb.append((char) len);
}
//5. 释放资源
isr.close();
//6. 返回数据
return sb.toString();
}
}
1.2 利用hutool包创建数据
与 1.1 不同的就是,hutool包给我们封装了,网络爬取的代码
即:
//2.爬取数据
String familyNameStr = HttpUtil.get(familyNameNet);
String girlNameStr = HttpUtil.get(girlNameNet);
String boyNameStr = HttpUtil.get(boyNameNet);
//3. 利用正则表达式获取数据
List<String> familyTempList = ReUtil.findAll("(.{4})(,|。)", familyNameStr, 1);
List<String> boyTempList = ReUtil.findAll("([\\u4E00-\\u9FA5]{2})(、|。)", boyNameStr, 1);
List<String> girlTempList = ReUtil.findAll("(.. ){4}..", girlNameStr, 0);
1.3 随机点名器
package IOExerciseMoreMore.myiotest2;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
//点名器1
/*
* 有一个文件里面存储了班级同学的信息,每一个信息占一行。
格式为:张三-男-23
要求通过程序实现随机点名器
* */
public class Test1 {
public static void main(String[] args) throws IOException {
//创建文本读取器
BufferedReader br = new BufferedReader(new FileReader("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest2\\names.txt"));
//读取数据
String len;
ArrayList<String> list = new ArrayList<>();//创建集合存储信息
while ((len = br.readLine()) != null){
list.add(len);
}
//打乱数据
Collections.shuffle(list);
//随机获取到数据
System.out.println("随机同学的名字为:"+list.get(0).split("-")[0]);
//清理资源
br.close();
}
}
package IOExerciseMoreMore.myiotest3;
import cn.hutool.system.oshi.OshiUtil;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Random;
//点名器2
/*
* 需求:
一个文件里面存储了班级同学的信息,每一个学生信息占一行
格式为:张三-男-23
要求通过程序实现随机点名器
*输出形式:
* 70%的概率随机到男生
30%的概率随机到女生
总共随机100万次,统计结果。
* */
public class Test1 {
public static void main(String[] args) throws IOException {
//创建字符读取器
BufferedReader br = new BufferedReader(new FileReader("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest3\\names3.txt"));
//将男生、女生的名字获取出来,放在不同的集合当中
ArrayList<String> boyName = new ArrayList<>();
ArrayList<String> girlName = new ArrayList<>();
String ch;
while ((ch = br.readLine()) != null){
if (ch.split("-")[1].equals("男")){
boyName.add(ch.split("-")[0]);
}else if (ch.split("-")[1].equals("女")){
girlName.add(ch.split("-")[0]);
}
}
//清理资源
br.close();
//创建一个集合添加名字,70%男生,30%女生
ArrayList<Integer> totalList = new ArrayList<>();
Collections.addAll(totalList,1,1,1,1,1,1,1,0,0,0);
//通过获取到的‘0’,‘1’来获取到是男生还是女生
Random r = new Random();
//定义两个变量计数
int girlCount = 0;
int boyCount = 0;
for (int i = 0; i < 1000000; i++) {
//随机从totalList当中获取到“0”“1”
int index = r.nextInt(totalList.size());
if (totalList.get(index) == 1){
//男生的名字
Collections.shuffle(boyName);
System.out.println(boyName.get(0));
boyCount++;
}else {
//女生的名字
Collections.shuffle(girlName);
System.out.println(girlName.get(0));
girlCount++;
}
}
System.out.println("男生出现的次数" + boyCount);
System.out.println("女生出现的次数" + girlCount);
}
}
package IOExerciseMoreMore.myiotest4;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
//点名器3
/*
* 运行效果:
第一次运行程序:随机同学姓名1
* 第二次运行程序:随机同学姓名2
第三次运行程序:张三
* */
public class Test1 {
public static void main(String[] args) throws IOException {
//创建文本读取器
BufferedReader br = new BufferedReader(new FileReader("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest2\\names.txt"));
//读取数据
String len;
ArrayList<String> list = new ArrayList<>();//创建集合存储信息
while ((len = br.readLine()) != null){
list.add(len);
}
//清理资源
br.close();
//打乱数据
Collections.shuffle(list);
//随机获取到数据
//读取当时作弊器的内容,若是第三次就直接打印张三,不是就随机谁的名字
FileReader zuoBiNum = new FileReader("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest4\\zuobiqi.txt");
int num;
if ((num=zuoBiNum.read())== '3'){
System.out.println("张三");
num++;
}else {
//随机获取到数据
System.out.println("随机同学的名字为:"+list.get(0).split("-")[0]);
num++;
}
FileWriter fw = new FileWriter("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest4\\zuobiqi.txt");
fw.write(num);
//关流
fw.close();
zuoBiNum.close();
}
}
package IOExerciseMoreMore.myiotest5;
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
/* 点名器4
* 被点到的学生不会再被点到
如果班级中所有的学生都点完了,
* 需要自动的重新开启第二轮点名
* 细节1:假设班级有10个学生,
* 每一轮中每一位学生只能被点到一次
* ,程序运行10次,第一轮结束
* 细节2:第11次运行的时候,我们自己不需要手动操作本地文件
* ,要求程序自动开始第二轮点名
* */
public class Test1 {
public static void main(String[] args) throws IOException {
File f1 = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest5\\names5.txt");
File f2 = new File("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest5\\a.txt");
//创建集合,添加数据进去
ArrayList<String> list = new ArrayList<>();
//读取名字到集合当中
BufferedReader br = new BufferedReader(new FileReader("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest5\\names5.txt"));
String ch;
while ((ch = br.readLine()) != null){
list.add(ch);
}
//清理资源
br.close();
//打乱数据,获取随机名字
Collections.shuffle(list);
String name = list.get(0).split("-")[0];
//将每个数据都放入到当前文件当中
BufferedWriter bw2 = new BufferedWriter(new FileWriter("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest5\\a.txt",true));
bw2.write(list.get(0));
bw2.newLine();
bw2.close();
//删除该元素
list.remove(0);
//将剩下的数据添加回原来的文件当中,再创建个文件存储数据
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest5\\names5.txt"));
for (String s : list) {
bw.write(s);
bw.newLine();
}
bw.close();
//当集合的长度为0时,代表结束
if(list.size() == 0){
//直接就复制文件
FileUtils.copyFile(f2,f1);
//将存储数据的文件初始化
cleanFile(f2);
}
}
private static void cleanFile(File f2) throws IOException {
FileWriter fw = new FileWriter(f2);
fw.write("");
fw.close();
}
}
package IOExerciseMoreMore.myiotest6;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
//带权重的点名器
/*
* 要求1: 每次被点到的学生,再次被点到的概率在原先的基础上降低一半。举例:80个学生,点名5次,每次都点到小A,概率变化情况如下:
第一次每人概率:1.25%。
第二次小A概率:0.625%。
第三次小A概率:03125%。
第四次小A概率:0.15625%。
第五次小A概率:0.078125%。
其他学生概率:1.2579%
* */
public class Test {
public static void main(String[] args) throws IOException {
//创建一个集合去存放Student对象
ArrayList<Student> list = new ArrayList<>();
//读取数据,将数据放入Student类当中方便管理
BufferedReader br = new BufferedReader(new FileReader("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest6\\names6.txt"));
String len;
while ((len = br.readLine()) != null) {
String[] arr= len.split("-");
Student student = new Student(arr[0], arr[1], Integer.parseInt(arr[2]), Double.parseDouble(arr[3]));
//将数据添加到list当中
list.add(student);
}
//回收资源
br.close();
//计算总的权重
Double weight = 0.0;
for (Student s : list) {
weight += s.getWeight();
}
//计算每个人的权重
Double[] arr = new Double[list.size()];
int index = 0;
for (Student s : list) {
arr[index] = s.getWeight()/weight;
index++;
}
//计算每个权重的范围
//就是 每一个元素前面的范围加上自己的范围
for (int i = 1; i < arr.length; i++) {
arr[i] = arr[i] + arr[i-1];
}
//获取到0-1范围的随机值
double r = Math.random();
//通过二分法来查看其位置,然后改变其权重
//返回的为 -位置 +1
//将其改变为当前的位置
int result = -Arrays.binarySearch(arr, r) - 1;
Student student = list.get(result);
//改变权重,被点到就把权重 /2
double newWeight = student.getWeight() / 2;
student.setWeight(newWeight);
//将数据重新写入到文件当中,储存起来
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\Java文件夹\\words\\IOExrecise\\src\\IOExerciseMoreMore\\myiotest6\\names6.txt"));
for (Student s : list) {
bw.write(s.toString());
bw.newLine();
}
//回收资源
bw.close();
}
}