目录
一、IO流的概述
1、IO流的分类
1.1、纯文本文件
2、小结
二、IO流的体系结构
三、字节流
1、FileOutputStream(字节输出流)
2、FileOutputStream写出数据的细节
3、FileOutputStream写数据的3种方式
3.1、一次写一个字节数据
3.2、一次写一个字节数组数据
3.3、一次写一个字节数组的部分数据
4、FileOutputStream写数据的两个小问题
4.1、换行写
4.2、续写
5、小结
6、FileInputStream(字节输入流)
7、FileInputStream书写细节
8、FileInputStream的循环读取
9、文件拷贝
9.1、文件拷贝的基本代码
9.2、文件拷贝的弊端
9.3、文件拷贝弊端的解决方案(一次读多个字节)
9.4、文件拷贝代码改写
10、IO流中不同JDK版本捕获异常的方式
四、字符集
1、ASCII字符集(0-127)
1.1、计算机的存储规则(英文)
2、GBK字符集
2.1、计算机的存储规则(英文)(GBK)
2.2、计算机的存储规则(汉字)(GBK)
3.3、小结
3、Unicode字符集
3.1、UTF-8是一个字符集吗?
3.2、Unicode字符集练习
3.3、小结
五、为什么会有乱码?
1、如何不产生乱码?
2、扩展
3、Java中的编解码方法
六、字符流
1、字符流的体系架构
2、FileReader(字符输入流)
2.1、创建字符输入流对象
2.2、读取数据
2.3、释放资源
3、FileWriter(字符输出流)
3.1、构造方法
3.2、成员方法
3.3、FileWriter书写细节
4、字符输出流写出数据
4.1、write(int c):写出一个字符
4.2、write(String str):写出一个字符串
4.3、write(char[] cbuf):写出一个字符数组
5、字符流原理解析
5.1、字符输入流(FileReader)的原理解析
5.2、字符输出流(FileWriter)的原理解析
七、综合练习
1、字节流和字符流的使用场景
2、练习一:拷贝(字节流)
3、练习二:文件加密
4、练习三:修改文件中的数据
八、IO流体系中的高级流
1、缓冲流
1.1、字节缓冲流
1.2、字节缓冲流提高效率的原理
1.3、字符缓冲流
1.4、小结
1.5、练习
1.5.1练习一:拷贝文件
1.5.2练习二:修改文本顺序
1.5.3练习三:软件的运行次数
2、转换流(字符流的一种)
2.1、转换流的基本用法
2,2、练习一:转换文件编码
2.3、练习二:读取文件中的数据
2.4、小结
3、序列化流/对象操作输出流(字节流的一种)(ObjectOutputStream)
3.1、构造方法&成员方法
3.2、利用序列化流,把一个对象写到本地文件中
3.3、序列化流的小细节(NotSerializableException)
4、反序列化流/对象操作输入流(ObjectInputStream)
4.1、利用反序列化流/对象操作输入流,把文件中的对象读到程序当中
4.2、序列号不匹配
4.3、瞬态关键字(不会把当前属性序列化到本地文件中)
4.4、小结编辑
4.5、综合练习:读写多个对象(先写再读)
5、打印流
5.1、字节打印流的构造方法
5.2、字节打印流的成员方法
5.3、占位符扩展
5.4、字符打印流的构造方法
5.5、字符打印流的成员方法
5.6、打印流的应用场景
5.7、小结
6、解压缩流/压缩流编辑
6.1、解压缩流
6.2、压缩流(压缩单个文件)
6.3、压缩流(压缩文件夹)
7、Commons-io
7.1、Commons-io使用步骤
7.2、Commons-io常见方法
8、Hutool工具包
8.1、IO包的封装类
8.2、FileUtil类
九、综合练习
1、制造假数据
1.1、爬取姓氏
1.2、爬取名字
1.3、数据处理
1.4、数据处理并写出
1.5、利用HuTool包生成假数据
2、随机点名器
2.1、练习1:普通随机点名
2.2、练习2:加入了概率和统计
2.3、练习3:作弊功能
2.4、练习4:随机不能重复,自动开启第二轮编辑
2.5、练习5:带权重的随机编辑
3、登录注册
3.1、练习1:写一个登录小案例
3.2、练习2:添加锁定账号功能
3.3、练习3:补全拼图小游戏的登录注册(考虑多个用户)
4、游戏的存档和读档
4.1、存档
4.2、读档编辑
4.3、修改bug
5、游戏配置
5.1、配置文件的优点
5.2、常见的配置文件
5.3、properties配置文件
5.4、Properties作为Map集合的操作
5.5、Properties跟IO流结合的操作(store)
5.6、读取Properties(load)
5.7、拼图游戏的配置文件
4、每日一记(IO的最终大作业)编辑
一、IO流的概述
IO流:存储和读取数据的解决方案
IO流和File是息息相关的
1、IO流的分类
1.1、纯文本文件
word、Excel不是纯文本文件
而txt或者md文件是纯文本文件
2、小结
二、IO流的体系结构
三、字节流
1、FileOutputStream(字节输出流)
代码
结果
2、FileOutputStream写出数据的细节
3、FileOutputStream写数据的3种方式
3.1、一次写一个字节数据
3.2、一次写一个字节数组数据
3.3、一次写一个字节数组的部分数据
4、FileOutputStream写数据的两个小问题
4.1、换行写
4.2、续写
5、小结
6、FileInputStream(字节输入流)
示例代码
7、FileInputStream书写细节
8、FileInputStream的循环读取
细节误区:
9、文件拷贝
9.1、文件拷贝的基本代码
课堂练习:要求统计一下拷贝时间,单位毫秒
9.2、文件拷贝的弊端
9.3、文件拷贝弊端的解决方案(一次读多个字节)
示例代码:
改进方法:
9.4、文件拷贝代码改写
10、IO流中不同JDK版本捕获异常的方式
示例代码
简化方案:(了解即可)
代码实现:(但在实际开发中几乎所有的异常都是抛出处理的)
JDK7
JDK9
四、字符集
1、ASCII字符集(0-127)
1.1、计算机的存储规则(英文)
编码:
解码:
2、GBK字符集
主要掌握
2.1、计算机的存储规则(英文)(GBK)
2.2、计算机的存储规则(汉字)(GBK)
高位字节二进制一定以1开头,是为了和英文做出区分
解码:(直接转成十进制即可)
3.3、小结
核心1: GBK中,一个英文字母一个字节,二进制第一位是0
核心2: GBK中,一个中文汉字两个字节,二进制第一位是1
3、Unicode字符集
为了减少浪费,那么就有了UTF-8编码规则:
3.1、UTF-8是一个字符集吗?
不是,UTF-8只是Unicode字符集的一种编码方式
3.2、Unicode字符集练习
3.3、小结
五、为什么会有乱码?
1、如何不产生乱码?
2、扩展
因为拷贝的时候是一个字节一个字节拷贝的,数据没有出现丢失,那么只要记事本打开的字符集和编码方式也和数据源保持一致,就不会出现乱码。
3、Java中的编解码方法
六、字符流
1、字符流的体系架构
2、FileReader(字符输入流)
2.1、创建字符输入流对象
//1.创建对象并关联本地文件
FileReader fr = new FileReader("myio\\a.txt");
2.2、读取数据
示例代码:(空参的read方法)
示例代码(带参的read方法)
//read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中 //空参的read + 强转类型转换
2.3、释放资源
示例代码:
3、FileWriter(字符输出流)
3.1、构造方法
3.2、成员方法
3.3、FileWriter书写细节
4、字符输出流写出数据
4.1、write(int c):写出一个字符
示例代码:(字节流,每次只能操作一个字节)
4.2、write(String str):写出一个字符串
4.3、write(char[] cbuf):写出一个字符数组
5、字符流原理解析
5.1、字符输入流(FileReader)的原理解析
示例代码:(底层揭秘)
Ⅰ、创建字符输入流对象
Ⅱ、读取数据
扩展:
5.2、字符输出流(FileWriter)的原理解析
数据会先写到缓冲区中
示例代码:(当出现字节数组装满了、被刷新、被关闭三种任意一种时,字节数组中的数据都会被写入到文件当中)
七、综合练习
1、字节流和字符流的使用场景
2、练习一:拷贝(字节流)
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test01 {
public static void main(String[] args) throws IOException {
//拷贝一个文件夹,考虑子文件夹
//1.创建对象表示数据源
File src = new File("D:\\aaa\\src");
//2.创建对象表示目的地
File dest = new File("D:\\aaa\\dest");
//3.调用方法开始拷贝
copydir(src,dest);
}
/*
* 作用:拷贝文件夹
* 参数一:数据源
* 参数二:目的地
*
* */
private static void copydir(File src, File dest) throws IOException {
dest.mkdirs();
//递归
//1.进入数据源
File[] files = src.listFiles();
//2.遍历数组
for (File file : files) {
if(file.isFile()){
//3.判断文件,拷贝
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));
byte[] bytes = new byte[1024];
int len;
while((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
}
fos.close();
fis.close();
}else {
//4.判断文件夹,递归
copydir(file, new File(dest,file.getName()));
}
}
}
}
3、练习二:文件加密
小知识:如果一个数字它异或另外一个数字两次,那么它得到的数字就是它本身
^ : 异或 两边相同:false 两边不同:true
加密:
解密:
4、练习三:修改文件中的数据
细节1: 文件中的数据不要换行 细节2: bom头
在utf-8编码文件中BOM在文件头部,占用三个字节,用来标示该文件属于utf-8编码。其实UTF-8 的BOM对UFT-8没有作用,是为了支援UTF-16,UTF-32才加上的BOM,BOM签名的意思就是告诉编辑器当前文件采用何种编码,方便编辑器识别,但是BOM虽然在编辑器中不显示,但是会产生输出,就像多了一个空行。
示例代码:(常规写法)
//1.读取数据
FileReader fr = new FileReader("myio\\a.txt");
StringBuilder sb = new StringBuilder();
int ch;
while((ch = fr.read()) != -1){
sb.append((char)ch);
}
fr.close();
System.out.println(sb);
//2.排序
String str = sb.toString();
String[] arrStr = str.split("-");//2-1-9-4-7-8
ArrayList<Integer> list = new ArrayList<>();
for (String s : arrStr) {
int i = Integer.parseInt(s);
list.add(i);
}
Collections.sort(list);
System.out.println(list);
//3.写出
FileWriter fw = new FileWriter("myio\\a.txt");
for (int i = 0; i < list.size(); i++) {
if(i == list.size() - 1){
fw.write(list.get(i) + "");
}else{
fw.write(list.get(i) + "-");
}
}
fw.close();
示例代码:(非常规写法—Stream && 方法引用)
//1.读取数据
FileReader fr = new FileReader("myio\\a.txt");
StringBuilder sb = new StringBuilder();
int ch;
while((ch = fr.read()) != -1){
sb.append((char)ch);
}
fr.close();
System.out.println(sb);
//2.排序
Integer[] arr = Arrays.stream(sb.toString()
.split("-"))
.map(Integer::parseInt)
.sorted()
.toArray(Integer[]::new);
//3.写出
FileWriter fw = new FileWriter("myio\\a.txt");
String s = Arrays.toString(arr).replace(", ","-");
String result = s.substring(1, s.length() - 1);
fw.write(result);
fw.close();
八、IO流体系中的高级流
1、缓冲流
1.1、字节缓冲流
缓冲流是一个高级流,是对基本流的一个包装
利用字节缓冲流拷贝文件:(示例代码)
需求: * 利用字节缓冲流拷贝文件 * * 字节缓冲输入流的构造方法: * public BufferedInputStream(InputStream is) * * 字节缓冲输出流的构造方法: * public BufferedOutputStream(OutputStream os)
默认缓冲区都是8192,基本流的关闭在底层会自动执行
//1.创建缓冲流的对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myio\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\a.txt"));
//2.循环读取并写到目的地
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
//3.释放资源
bos.close();
bis.close();
利用字节缓冲流拷贝文件:(一次读写多个字节)
//1.创建缓冲流的对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myio\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\copy2.txt"));
//2.拷贝(一次读写多个字节)
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
//3.释放资源
bos.close();
bis.close();
1.2、字节缓冲流提高效率的原理
倒手的过程是在内存中发生的,而内存的速度是非常快的,几乎可以忽略不计
它真正节约的是读和写的时候跟硬盘之间打交道的时间,其根本原因是因为字节流默认不使用缓冲区;切勿与字符流搞混
1.3、字符缓冲流
但是因为字符流本身就带有缓冲区,所以字符缓冲流对效率的提升就不是很明显。
构造方法:
特有方法:
package com.yaqi.mybufferedstream1;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedStreamDemo3 {
public static void main(String[] args) throws IOException {
/*
* 字符缓冲输入流:
* 构造方法:
* public BufferedReader(Reader r)
* 特有方法:
* public String readLine() 读一整行
*
* */
//1.创建字符缓冲输入流的对象
BufferedReader br = new BufferedReader(new FileReader("myio\\a.txt"));
//2.读取数据
//细节:
//readLine方法在读取的时候,一次读一整行,遇到回车换行结束
// 但是他不会把回车换行读到内存当中
/* String line1 = br.readLine();
System.out.println(line1);
String line2 = br.readLine();
System.out.println(line2);*/
String line;
while ((( line = br.readLine()) != null)){
System.out.println(line);
}
//3.释放资源
br.close();
}
}
1.4、小结
1.5、练习
1.5.1练习一:拷贝文件
package com.yaqi.mytest;
import java.io.*;
public class Test05 {
public static void main(String[] args) throws IOException {
/*
四种方式拷贝文件,并统计各自用时
*/
long start = System.currentTimeMillis();
//method1();
//method2(); //16.253秒
//method3(); //95.466秒
//method4(); //17.686秒
long end = System.currentTimeMillis();
System.out.println((end - start) / 1000.0 + "秒");
}
//字节流的基本流:一次读写一个字节4,588,568,576 字节
public static void method1() throws IOException {
FileInputStream fis = new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso");
FileOutputStream fos = new FileOutputStream("myio\\copy.iso");
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
fos.close();
fis.close();
}
//字节流的基本流:一次读写一个字节数组
public static void method2() throws IOException {
FileInputStream fis = new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso");
FileOutputStream fos = new FileOutputStream("myio\\copy.iso");
byte[] bytes = new byte[8192];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
fos.close();
fis.close();
}
//字节流的基本流:一次读写一个字节数组
public static void method3() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\copy.iso"));
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
bos.close();
bis.close();
}
//字节流的基本流:一次读写一个字节数组
public static void method4() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\aaa\\CentOS-7-x86_64-DVD-1810.iso"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\copy.iso"));
byte[] bytes = new byte[8192];
int len;
while ((len = bis.read(bytes)) != -1) {
bos.write(bytes, 0, len);
}
bos.close();
bis.close();
}
}
1.5.2练习二:修改文本顺序
示例代码:(Collections排序)
示例代码:(TreeMap排序)
1.5.3练习三:软件的运行次数
实现一个验证程序运行次数的小程序,要求如下: 1.当程序运行超过3次时给出提示:本软件只能免费使用3次,欢迎您注册会员后继续使用~ 2.程序运行演示如下: 第一次运行控制台输出: 欢迎使用本软件,第1次使用免费~ 第二次运行控制台输出: 欢迎使用本软件,第2次使用免费~ 第三次运行控制台输出: 欢迎使用本软件,第3次使用免费~ 第四次及之后运行控制台输出:本软件只能免费使用3次,欢迎您注册会员后继续使用~
//原则:
//IO:随用随创建
// 什么时候不用什么时候关闭
2、转换流(字符流的一种)
转换流是字符流和字节流之间的桥梁
2.1、转换流的基本用法
指定字符集读取:
package com.yaqi.myconvertstream;
import java.io.*;
import java.nio.charset.Charset;
public class ConvertStreamDemo1 {
public static void main(String[] args) throws IOException {
/*
利用转换流按照指定字符编码读取(了解)
因为JDK11:这种方式被淘汰了。替代方案(掌握)
F:\JavaSE最新版\day29-IO(其他流)\资料\gbkfile.txt
*/
/* //1.创建对象并指定字符编码
InputStreamReader isr = new InputStreamReader(new FileInputStream("myio\\gbkfile.txt"),"GBK");
//2.读取数据
int ch;
while ((ch = isr.read()) != -1){
System.out.print((char)ch);
}
//3.释放资源
isr.close();*/
FileReader fr = new FileReader("myio\\gbkfile.txt", Charset.forName("GBK"));
//2.读取数据
int ch;
while ((ch = fr.read()) != -1){
System.out.print((char)ch);
}
//3.释放资源
fr.close();
}
}
利用转换流按照指定字符编码写出数据:
import java.io.*;
import java.nio.charset.Charset;
public class ConvertStreamDemo2 {
public static void main(String[] args) throws IOException {
/*
利用转换流按照指定字符编码写出
*/
/*
//1.创建转换流的对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myio\\b.txt"),"GBK");
//2.写出数据
osw.write("你好你好");
//3.释放资源
osw.close();*/
FileWriter fw = new FileWriter("myio\\c.txt", Charset.forName("GBK"));
fw.write("你好你好");
fw.close();
}
}
2,2、练习一:转换文件编码
将本地文件中的GBK文件,转成UTF-8
package com.yaqi.myconvertstream;
import java.io.*;
import java.nio.charset.Charset;
public class ConvertStreamDemo3 {
public static void main(String[] args) throws IOException {
/*
将本地文件中的GBK文件,转成UTF-8
*/
//1.JDK11以前的方案
/* InputStreamReader isr = new InputStreamReader(new FileInputStream("myio\\b.txt"),"GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myio\\d.txt"),"UTF-8");
int b;
while((b = isr.read()) != -1){
osw.write(b);
}
osw.close();
isr.close();*/
//2.替代方案
FileReader fr = new FileReader("myio\\b.txt", Charset.forName("GBK"));
FileWriter fw = new FileWriter("myio\\e.txt",Charset.forName("UTF-8"));
int b;
while ((b = fr.read()) != -1){
fw.write(b);
}
fw.close();
fr.close();
}
}
2.3、练习二:读取文件中的数据
package com.yaqi.myconvertstream;
import java.io.*;
public class ConvertStreamDemo4 {
public static void main(String[] args) throws IOException {
/*
利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
//1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定
//2.字节流里面是没有读一整行的方法的,只有字符缓冲流才能搞定
*/
/* FileInputStream fis = new FileInputStream("myio\\a.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String str = br.readLine();
System.out.println(str);
br.close();*/
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("myio\\a.txt")));
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}
}
2.4、小结
3、序列化流/对象操作输出流(字节流的一种)(ObjectOutputStream)
3.1、构造方法&成员方法
3.2、利用序列化流,把一个对象写到本地文件中
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectStreamDemo1 {
public static void main(String[] args) throws IOException {
/*
需求:
利用序列化流/对象操作输出流,把一个对象写到本地文件中
构造方法:
public ObjectOutputStream(OutputStream out) 把基本流变成高级流
成员方法:
public final void writeObject(Object obj) 把对象序列化(写出)到文件中去
*/
//1.创建对象
Student stu = new Student("zhangsan",23,"南京");
//2.创建序列化流的对象/对象操作输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myio\\a.txt"));
//3.写出数据
oos.writeObject(stu);
//4.释放资源
oos.close();
}
}
3.3、序列化流的小细节(NotSerializableException)
4、反序列化流/对象操作输入流(ObjectInputStream)
4.1、利用反序列化流/对象操作输入流,把文件中的对象读到程序当中
4.2、序列号不匹配
如果一个类实现了序列化接口Serializable,那么就表示这个类的对象是可被序列化的
解决方案:固定版本号
方法一: 手动书写
方法二:设置Idea,让其自动书写
Settings -> 搜索Serializable -> 勾选下方两个选项 -> Apply |
方法三:搜索Java中已经写好的一个类,如ArrayList,然后复制它的
4.3、瞬态关键字(不会把当前属性序列化到本地文件中)
如果你在JavaBean中有哪个属性是不想让它进行序列化,就给它加上transient关键字
4.4、小结
4.5、综合练习:读写多个对象(先写再读)
序列化多个对象:
反序列化:
5、打印流
5.1、字节打印流的构造方法
5.2、字节打印流的成员方法
示例代码:
5.3、占位符扩展
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Date;
public class PrintStreamDemo2 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("a.txt");
//% n表示换行
ps.printf("我叫%s %n", "阿玮");
ps.printf("%s喜欢%s %n", "阿珍", "阿强");
ps.printf("字母H的大写:%c %n", 'H');
ps.printf("8>3的结果是:%b %n", 8 > 3);
ps.printf("100的一半是:%d %n", 100 / 2);
ps.printf("100的16进制数是:%x %n", 100);
ps.printf("100的8进制数是:%o %n", 100);
ps.printf("50元的书打8.5折扣是:%f元%n", 50 * 0.85);
ps.printf("计算的结果转16进制:%a %n", 50 * 0.85);
ps.printf("计算的结果转科学计数法表示:%e %n", 50 * 0.85);
ps.printf("计算的结果转成指数和浮点数,结果的长度较短的是:%g %n", 50 * 0.85);
ps.printf("带有百分号的符号表示法,以百分之85为例:%d%% %n", 85);
ps.println("---------------------");
double num1 = 1.0;
ps.printf("num: %.4g %n", num1);
ps.printf("num: %.5g %n", num1);
ps.printf("num: %.6g %n", num1);
float num2 = 1.0F;
ps.printf("num: %.4f %n", num2);
ps.printf("num: %.5f %n", num2);
ps.printf("num: %.6f %n", num2);
ps.println("---------------------");
ps.printf("数字前面带有0的表示方式:%03d %n", 7);
ps.printf("数字前面带有0的表示方式:%04d %n", 7);
ps.printf("数字前面带有空格的表示方式:% 8d %n", 7);
ps.printf("整数分组的效果是:%,d %n", 9989997);
ps.println("---------------------");
//最终结果是10位,小数点后面是5位,不够在前面补空格,补满10位
//如果实际数字小数点后面过长,但是只规定两位,会四舍五入
//如果整数部分过长,超出规定的总长度,会以实际为准
ps.printf("一本书的价格是:%2.5f元%n", 49.8);
ps.printf("%(f%n", -76.04);
//%f,默认小数点后面7位,
//<,表示采取跟前面一样的内容
ps.printf("%f和%3.2f %n", 86.04, 1.789651);
ps.printf("%f和%<3.2f %n", 86.04, 1.789651);
ps.println("---------------------");
Date date = new Date();
// %t 表示时间,但是不能单独出现,要指定时间的格式
// %tc 周二 12月 06 22:08:40 CST 2022
// %tD 斜线隔开
// %tF 冒号隔开(12小时制)
// %tr 冒号隔开(24小时制)
// %tT 冒号隔开(24小时制,带时分秒)
ps.printf("全部日期和时间信息:%tc %n", date);
ps.printf("月/日/年格式:%tD %n", date);
ps.printf("年-月-日格式:%tF %n", date);
ps.printf("HH:MM:SS PM格式(12时制):%tr %n", date);
ps.printf("HH:MM格式(24时制):%tR %n", date);
ps.printf("HH:MM:SS格式(24时制):%tT %n", date);
System.out.println("---------------------");
ps.printf("星期的简称:%ta %n", date);
ps.printf("星期的全称:%tA %n", date);
ps.printf("英文月份简称:%tb %n", date);
ps.printf("英文月份全称:%tB %n", date);
ps.printf("年的前两位数字(不足两位前面补0):%tC %n", date);
ps.printf("年的后两位数字(不足两位前面补0):%ty %n", date);
ps.printf("一年中的第几天:%tj %n", date);
ps.printf("两位数字的月份(不足两位前面补0):%tm %n", date);
ps.printf("两位数字的日(不足两位前面补0):%td %n", date);
ps.printf("月份的日(前面不补0):%te %n", date);
System.out.println("---------------------");
ps.printf("两位数字24时制的小时(不足2位前面补0):%tH %n", date);
ps.printf("两位数字12时制的小时(不足2位前面补0):%tI %n", date);
ps.printf("两位数字24时制的小时(前面不补0):%tk %n", date);
ps.printf("两位数字12时制的小时(前面不补0):%tl %n", date);
ps.printf("两位数字的分钟(不足2位前面补0):%tM %n", date);
ps.printf("两位数字的秒(不足2位前面补0):%tS %n", date);
ps.printf("三位数字的毫秒(不足3位前面补0):%tL %n", date);
ps.printf("九位数字的毫秒数(不足9位前面补0):%tN %n", date);
ps.printf("小写字母的上午或下午标记(英):%tp %n", date);
ps.printf("小写字母的上午或下午标记(中):%tp %n", date);
ps.printf("相对于GMT的偏移量:%tz %n", date);
ps.printf("时区缩写字符串:%tZ%n", date);
ps.printf("1970-1-1 00:00:00 到现在所经过的秒数:%ts %n", date);
ps.printf("1970-1-1 00:00:00 到现在所经过的毫秒数:%tQ %n", date);
ps.close();
}
}
我叫阿玮 阿珍喜欢阿强 字母H的大写:H 8>3的结果是:true 100的一半是:50 100的16进制数是:64 100的8进制数是:144 50元的书打8.5折扣是:42.500000元 计算的结果转16进制:0x1.54p5 计算的结果转科学计数法表示:4.250000e+01 计算的结果转成指数和浮点数,结果的长度较短的是:42.5000 带有百分号的符号表示法,以百分之85为例:85% --------------------- num: 1.000 num: 1.0000 num: 1.00000 num: 1.0000 num: 1.00000 num: 1.000000 --------------------- 数字前面带有0的表示方式:007 数字前面带有0的表示方式:0007 数字前面带有空格的表示方式: 7 整数分组的效果是:9,989,997 --------------------- 一本书的价格是:49.80000元 (76.040000) 86.040000和1.79 86.040000和86.04 --------------------- 全部日期和时间信息:周六 2月 17 11:14:21 CST 2024 月/日/年格式:02/17/24 年-月-日格式:2024-02-17 HH:MM:SS PM格式(12时制):11:14:21 上午 HH:MM格式(24时制):11:14 HH:MM:SS格式(24时制):11:14:21 星期的简称:周六 星期的全称:星期六 英文月份简称:2月 英文月份全称:二月 年的前两位数字(不足两位前面补0):20 年的后两位数字(不足两位前面补0):24 一年中的第几天:048 两位数字的月份(不足两位前面补0):02 两位数字的日(不足两位前面补0):17 月份的日(前面不补0):17 两位数字24时制的小时(不足2位前面补0):11 两位数字12时制的小时(不足2位前面补0):11 两位数字24时制的小时(前面不补0):11 两位数字12时制的小时(前面不补0):11 两位数字的分钟(不足2位前面补0):14 两位数字的秒(不足2位前面补0):21 三位数字的毫秒(不足3位前面补0):160 九位数字的毫秒数(不足9位前面补0):160000000 小写字母的上午或下午标记(英):上午 小写字母的上午或下午标记(中):上午 相对于GMT的偏移量:+0800 时区缩写字符串:CST 1970-1-1 00:00:00 到现在所经过的秒数:1708139661 1970-1-1 00:00:00 到现在所经过的毫秒数:1708139661160
5.4、字符打印流的构造方法
5.5、字符打印流的成员方法
示例代码:
5.6、打印流的应用场景
5.7、小结
6、解压缩流/压缩流
6.1、解压缩流
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/*
* 解压缩流
*
* */
public class ZipStreamDemo1 {
public static void main(String[] args) throws IOException {
//1.创建一个File表示要解压的压缩包
File src = new File("D:\\aaa.zip");
//2.创建一个File表示解压的目的地
File dest = new File("D:\\");
//调用方法
unzip(src,dest);
}
//定义一个方法用来解压
public static void unzip(File src,File dest) throws IOException {
//解压的本质:把压缩包里面的每一个文件或者文件夹读取出来,按照层级拷贝到目的地当中
//创建一个解压缩流用来读取压缩包中的数据
ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
//要先获取到压缩包里面的每一个zipentry对象
//表示当前在压缩包中获取到的文件或者文件夹
ZipEntry entry;
while((entry = zip.getNextEntry()) != null){
System.out.println(entry);
if(entry.isDirectory()){
//文件夹:需要在目的地dest处创建一个同样的文件夹
File file = new File(dest,entry.toString());
file.mkdirs();
}else{
//文件:需要读取到压缩包中的文件,并把他存放到目的地dest文件夹中(按照层级目录进行存放)
FileOutputStream fos = new FileOutputStream(new File(dest,entry.toString()));
int b;
while((b = zip.read()) != -1){
//写到目的地
fos.write(b);
}
fos.close();
//表示在压缩包中的一个文件处理完毕了。
zip.closeEntry();
}
}
zip.close();
}
}
6.2、压缩流(压缩单个文件)
package com.yaqi.myzipstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipStreamDemo2 {
public static void main(String[] args) throws IOException {
/*
* 压缩流
* 需求:
* 把D:\\a.txt打包成一个压缩包
* */
//1.创建File对象表示要压缩的文件
File src = new File("D:\\a.txt");
//2.创建File对象表示压缩包的位置
File dest = new File("D:\\");
//3.调用方法用来压缩
toZip(src,dest);
}
/*
* 作用:压缩
* 参数一:表示要压缩的文件
* 参数二:表示压缩包的位置
* */
public static void toZip(File src,File dest) throws IOException {
//1.创建压缩流关联压缩包
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
//2.创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
//参数:压缩包里面的路径
ZipEntry entry = new ZipEntry("aaa\\bbb\\a.txt");
//3.把ZipEntry对象放到压缩包当中
zos.putNextEntry(entry);
//4.把src文件中的数据写到压缩包当中
FileInputStream fis = new FileInputStream(src);
int b;
while((b = fis.read()) != -1){
zos.write(b);
}
zos.closeEntry();
zos.close();
}
}
6.3、压缩流(压缩文件夹)
package com.yaqi.myzipstream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipStreamDemo3 {
public static void main(String[] args) throws IOException {
/*
* 压缩流
* 需求:
* 把D:\\aaa文件夹压缩成一个压缩包
* */
//1.创建File对象表示要压缩的文件夹
File src = new File("D:\\aaa");
//2.创建File对象表示压缩包放在哪里(压缩包的父级路径)
File destParent = src.getParentFile();//D:\\
//3.创建File对象表示压缩包的路径
File dest = new File(destParent,src.getName() + ".zip");
//4.创建压缩流关联压缩包
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
//5.获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
toZip(src,zos,src.getName());//aaa
//6.释放资源
zos.close();
}
/*
* 作用:获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
* 参数一:数据源
* 参数二:压缩流
* 参数三:压缩包内部的路径
* */
public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {
//1.进入src文件夹
File[] files = src.listFiles();
//2.遍历数组
for (File file : files) {
if(file.isFile()){
//3.判断-文件,变成ZipEntry对象,放入到压缩包当中
ZipEntry entry = new ZipEntry(name + "\\" + file.getName());//aaa\\no1\\a.txt
zos.putNextEntry(entry);
//读取文件中的数据,写到压缩包
FileInputStream fis = new FileInputStream(file);
int b;
while((b = fis.read()) != -1){
zos.write(b);
}
fis.close();
zos.closeEntry();
}else{
//4.判断-文件夹,递归
toZip(file,zos,name + "\\" + file.getName());
// no1 aaa \\ no1
}
}
}
}
7、Commons-io
7.1、Commons-io使用步骤
7.2、Commons-io常见方法
//复制文件
File src = new File("myio\\a.txt");
File dest = new File("myio\\copy.txt");
FileUtils.copyFile(src,dest);
//复制文件夹
File src = new File("D:\\aaa");
File dest = new File("D:\\bbb");
FileUtils.copyDirectoryToDirectory(src,dest);
ToDirectory:相当于把源文件夹原封不动的拷贝到dest文件夹里面
FileUtils.copyDirectoryToDirectory(src,dest);
//删除文件夹
File src = new File("D:\\aaa");
FileUtils.deleteDirectory(src);
示例代码:(清空文件夹):文件夹里面的内容删除了,但是根文件夹还存在
//清空文件夹
File src = new File("D:\\bbb");
FileUtils.cleanDirectory(src);
8、Hutool工具包
官网: http:// https://hutool.cn/
API文档:https://apidoc.gitee.com/dromara/hutool/
中文使用文档:http:// https://hutool.cn/docs/#/
8.1、IO包的封装类
8.2、FileUtil类
FileUtil类:
file:根据参数创建一个file对象
touch:根据参数创建文件
writeLines:把集合中的数据写出到文件中,覆盖模式。
appendLines:把集合中的数据写出到文件中,续写模式。
readLines:指定字符编码,把文件中的数据,读到集合中。
readUtf8Lines:按照UTF-8的形式,把文件中的数据,读到集合中
copy:拷贝文件或者文件夹
*//* File file1 = FileUtil.file("D:\\", "aaa", "bbb", "a.txt");
System.out.println(file1);//D:\aaa\bbb\a.txt
File touch = FileUtil.touch(file1);
System.out.println(touch);
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("aaa");
list.add("aaa");
File file2 = FileUtil.writeLines(list, "D:\\a.txt", "UTF-8");
System.out.println(file2);*//*
*//* ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("aaa");
list.add("aaa");
File file3 = FileUtil.appendLines(list, "D:\\a.txt", "UTF-8");
System.out.println(file3);*//*
List<String> list = FileUtil.readLines("D:\\a.txt", "UTF-8");
System.out.println(list);
}
九、综合练习
1、制造假数据
package com.yaqi.myiotest1;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test1 {
public static void main(String[] args) throws IOException {
/*
制造假数据:
获取姓氏:https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0
获取男生名字:http://www.haoming8.cn/baobao/10881.html
获取女生名字:http://www.haoming8.cn/baobao/7641.html
*/
//1.定义变量记录网址
String familyNameNet = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";
//2.爬取数据,把网址上所有的数据拼接成一个字符串
String familyNameStr = webCrawler(familyNameNet);
String boyNameStr = webCrawler(boyNameNet);
String girlNameStr = webCrawler(girlNameNet);
//3.通过正则表达式,把其中符合要求的数据获取出来
ArrayList<String> familyNameTempList = getData(familyNameStr,"(.{4})(,|。)",1);
ArrayList<String> boyNameTempList = getData(boyNameStr,"([\\u4E00-\\u9FA5]{2})(、|。)",1);
ArrayList<String> girlNameTempList = getData(girlNameStr,"(.. ){4}..",0);
//4.处理数据
//familyNameTempList(姓氏)
//处理方案:把每一个姓氏拆开并添加到一个新的集合当中
ArrayList<String> familyNameList = new ArrayList<>();
for (String str : familyNameTempList) {
//str 赵钱孙李 周吴郑王 冯陈褚卫 蒋沈韩杨
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
familyNameList.add(c + "");
}
}
//boyNameTempList(男生的名字)
//处理方案:去除其中的重复元素
ArrayList<String> boyNameList = new ArrayList<>();
for (String str : boyNameTempList) {
if(!boyNameList.contains(str)){
boyNameList.add(str);
}
}
//girlNameTempList(女生的名字)
//处理方案:把里面的每一个元素用空格进行切割,得到每一个女生的名字
ArrayList<String> girlNameList = new ArrayList<>();
for (String str : girlNameTempList) {
String[] arr = str.split(" ");
for (int i = 0; i < arr.length; i++) {
girlNameList.add(arr[i]);
}
}
//5.生成数据
//姓名(唯一)-性别-年龄
ArrayList<String> list = getInfos(familyNameList, boyNameList, girlNameList, 70, 50);
Collections.shuffle(list);
//6.写出数据
BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\names.txt"));
for (String str : list) {
bw.write(str);
bw.newLine();
}
bw.close();
}
/*
* 作用:
* 获取男生和女生的信息:张三-男-23
*
* 形参:
* 参数一:装着姓氏的集合
* 参数二:装着男生名字的集合
* 参数三:装着女生名字的集合
* 参数四:男生的个数
* 参数五:女生的个数
* */
public static ArrayList<String> getInfos(ArrayList<String> familyNameList,ArrayList<String> boyNameList,ArrayList<String> girlNameList, int boyCount,int girlCount){
//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));
}
//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));
}
//3.生成男生的信息并添加到集合当中
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
//【18 ~ 27】
for (String boyName : boyhs) {
//boyName依次表示每一个男生的名字
int age = r.nextInt(10) + 18;
list.add(boyName + "-男-" + age);
}
//4.生成女生的信息并添加到集合当中
//【18 ~ 25】
for (String girlName : girlhs) {
//girlName依次表示每一个女生的名字
int age = r.nextInt(8) + 18;
list.add(girlName + "-女-" + age);
}
return list;
}
/*
* 作用:根据正则表达式获取字符串中的数据
* 参数一:
* 完整的字符串
* 参数二:
* 正则表达式
* 参数三:
* 获取数据
* 0:获取符合正则表达式所有的内容
* 1:获取正则表达式中第一组数据
* 2:获取正则表达式中第二组数据
* ...以此类推
*
* 返回值:
* 真正想要的数据
*
* */
private static ArrayList<String> getData(String str, String regex,int index) {
//1.创建集合存放数据
ArrayList<String> list = new ArrayList<>();
//2.按照正则表达式的规则,去获取数据
Pattern pattern = Pattern.compile(regex);
//按照pattern的规则,到str当中获取数据
Matcher matcher = pattern.matcher(str);
while (matcher.find()){
list.add(matcher.group(index));
}
return list;
}
/*
* 作用:
* 从网络中爬取数据,把数据拼接成字符串返回
* 形参:
* 网址
* 返回值:
* 爬取到的所有数据
* */
public static String webCrawler(String net) throws IOException {
//1.定义StringBuilder拼接爬取到的数据
StringBuilder sb = new StringBuilder();
//2.创建一个URL对象
URL url = new URL(net);
//3.链接上这个网址
//细节:保证网络是畅通的,而且这个网址是可以链接上的。
URLConnection conn = url.openConnection();
//4.读取数据
InputStreamReader isr = new InputStreamReader(conn.getInputStream());
int ch;
while ((ch = isr.read()) != -1){
sb.append((char)ch);
}
//5.释放资源
isr.close();
//6.把读取到的数据返回
return sb.toString();
}
}
1.1、爬取姓氏
/*
* 作用:
* 从网络中爬取数据,把数据拼接成字符串返回
* 形参:
* 网址
* 返回值:
* 爬取到的所有数据
* */
public static String webCrawler(String net) throws IOException {
//1.定义StringBuilder拼接爬取到的数据
StringBuilder sb = new StringBuilder();
//2.创建一个URL对象
URL url = new URL(net);
//3.链接上这个网址
//细节:保证网络是畅通的,而且这个网址是可以链接上的。
URLConnection conn = url.openConnection();
//4.读取数据
InputStreamReader isr = new InputStreamReader(conn.getInputStream());
int ch;
while ((ch = isr.read()) != -1){
sb.append((char)ch);
}
//5.释放资源
isr.close();
//6.把读取到的数据返回
return sb.toString();
}
}
/*
* 作用:根据正则表达式获取字符串中的数据
* 参数一:
* 完整的字符串
* 参数二:
* 正则表达式
* 参数三:
* 获取数据
* 0:获取符合正则表达式所有的内容
* 1:获取正则表达式中第一组数据
* 2:获取正则表达式中第二组数据
* ...以此类推
*
* 返回值:
* 真正想要的数据
*
* */
private static ArrayList<String> getData(String str, String regex,int index) {
//1.创建集合存放数据
ArrayList<String> list = new ArrayList<>();
//2.按照正则表达式的规则,去获取数据
Pattern pattern = Pattern.compile(regex);
//按照pattern的规则,到str当中获取数据
Matcher matcher = pattern.matcher(str);
while (matcher.find()){
list.add(matcher.group(index));
}
return list;
}
/*
制造假数据:
获取姓氏:https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0
获取男生名字:http://www.haoming8.cn/baobao/10881.html
获取女生名字:http://www.haoming8.cn/baobao/7641.html
*/
//1.定义变量记录网址
String familyNameNet = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";
//2.爬取数据,把网址上所有的数据拼接成一个字符串
String familyNameStr = webCrawler(familyNameNet);
String boyNameStr = webCrawler(boyNameNet);
String girlNameStr = webCrawler(girlNameNet);
//3.通过正则表达式,把其中符合要求的数据获取出来
ArrayList<String> familyNameTempList = getData(familyNameStr,"(.{4})(,|。)",1);
ArrayList<String> boyNameTempList = getData(boyNameStr,"([\\u4E00-\\u9FA5]{2})(、|。)",1);
ArrayList<String> girlNameTempList = getData(girlNameStr,"(.. ){4}..",0);
1.2、爬取名字
//3.通过正则表达式,把其中符合要求的数据获取出来
ArrayList<String> familyNameTempList = getData(familyNameStr,"(.{4})(,|。)",1);
ArrayList<String> boyNameTempList = getData(boyNameStr,"([\\u4E00-\\u9FA5]{2})(、|。)",1);
ArrayList<String> girlNameTempList = getData(girlNameStr,"(.. ){4}..",0);
1.3、数据处理
//4.处理数据
//familyNameTempList(姓氏)
//处理方案:把每一个姓氏拆开并添加到一个新的集合当中
ArrayList<String> familyNameList = new ArrayList<>();
for (String str : familyNameTempList) {
//str 赵钱孙李 周吴郑王 冯陈褚卫 蒋沈韩杨
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
familyNameList.add(c + "");
}
}
//boyNameTempList(男生的名字)
//处理方案:去除其中的重复元素
ArrayList<String> boyNameList = new ArrayList<>();
for (String str : boyNameTempList) {
if(!boyNameList.contains(str)){
boyNameList.add(str);
}
}
//girlNameTempList(女生的名字)
//处理方案:把里面的每一个元素用空格进行切割,得到每一个女生的名字
ArrayList<String> girlNameList = new ArrayList<>();
for (String str : girlNameTempList) {
String[] arr = str.split(" ");
for (int i = 0; i < arr.length; i++) {
girlNameList.add(arr[i]);
}
}
1.4、数据处理并写出
//5.生成数据
//姓名(唯一)-性别-年龄
ArrayList<String> list = getInfos(familyNameList, boyNameList, girlNameList, 70, 50);
Collections.shuffle(list);
//6.写出数据
BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\names.txt"));
for (String str : list) {
bw.write(str);
bw.newLine();
}
bw.close();
}
/*
* 作用:
* 获取男生和女生的信息:张三-男-23
*
* 形参:
* 参数一:装着姓氏的集合
* 参数二:装着男生名字的集合
* 参数三:装着女生名字的集合
* 参数四:男生的个数
* 参数五:女生的个数
* */
public static ArrayList<String> getInfos(ArrayList<String> familyNameList,ArrayList<String> boyNameList,ArrayList<String> girlNameList, int boyCount,int girlCount){
//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));
}
//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));
}
//3.生成男生的信息并添加到集合当中
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
//【18 ~ 27】
for (String boyName : boyhs) {
//boyName依次表示每一个男生的名字
int age = r.nextInt(10) + 18;
list.add(boyName + "-男-" + age);
}
//4.生成女生的信息并添加到集合当中
//【18 ~ 25】
for (String girlName : girlhs) {
//girlName依次表示每一个女生的名字
int age = r.nextInt(8) + 18;
list.add(girlName + "-女-" + age);
}
return list;
}
//6.写出数据
BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\names.txt"));
for (String str : list) {
bw.write(str);
bw.newLine();
}
bw.close();
1.5、利用HuTool包生成假数据
package com.yaqi.myiotest1;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.http.HttpUtil;
import java.util.*;
public class Test2 {
public static void main(String[] args){
//利用糊涂包生成假数据,并写到文件当中
//1. 定义网址
String familyNameNet = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
String boyNameNet = "http://www.haoming8.cn/baobao/10881.html";
String girlNameNet = "http://www.haoming8.cn/baobao/7641.html";
//2.爬取数据
String familyNameStr = HttpUtil.get(familyNameNet);
String boyNameStr = HttpUtil.get(boyNameNet);
String girlNameStr = HttpUtil.get(girlNameNet);
//3.利用正则表达式获取数据
//通过正则表达式,把其中符合要求的数据获取出来
List<String> familyNameTempList = ReUtil.findAll("(.{4})(,|。)", familyNameStr, 1);
List<String> boyNameTempList = ReUtil.findAll("([\\u4E00-\\u9FA5]{2})(、|。)", boyNameStr, 1);
List<String> girlNameTempList = ReUtil.findAll("(.. ){4}..", girlNameStr, 0);
System.out.println(familyNameTempList);
System.out.println(boyNameTempList);
System.out.println(girlNameTempList);
//4.处理数据
//familyNameTempList(姓氏)
//处理方案:把每一个姓氏拆开并添加到一个新的集合当中
ArrayList<String> familyNameList = new ArrayList<>();
for (String str : familyNameTempList) {
//str 赵钱孙李 周吴郑王 冯陈褚卫 蒋沈韩杨
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
familyNameList.add(c + "");
}
}
//boyNameTempList(男生的名字)
//处理方案:去除其中的重复元素
ArrayList<String> boyNameList = new ArrayList<>();
for (String str : boyNameTempList) {
if(!boyNameList.contains(str)){
boyNameList.add(str);
}
}
//girlNameTempList(女生的名字)
//处理方案:把里面的每一个元素用空格进行切割,得到每一个女生的名字
ArrayList<String> girlNameList = new ArrayList<>();
for (String str : girlNameTempList) {
String[] arr = str.split(" ");
for (int i = 0; i < arr.length; i++) {
girlNameList.add(arr[i]);
}
}
//5.生成数据
//姓名(唯一)-性别-年龄
ArrayList<String> list = getInfos(familyNameList, boyNameList, girlNameList, 70, 50);
Collections.shuffle(list);
//6.写出数据
//细节:
//糊涂包的相对路径,不是相对于当前项目而言的,而是相对class文件而言的
FileUtil.writeLines(list,"D:\\names.txt","UTF-8");
}
/*
* 作用:
* 获取男生和女生的信息:张三-男-23
*
* 形参:
* 参数一:装着姓氏的集合
* 参数二:装着男生名字的集合
* 参数三:装着女生名字的集合
* 参数四:男生的个数
* 参数五:女生的个数
* */
public static ArrayList<String> getInfos(ArrayList<String> familyNameList,ArrayList<String> boyNameList,ArrayList<String> girlNameList, int boyCount,int girlCount){
//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));
}
//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));
}
//3.生成男生的信息并添加到集合当中
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
//【18 ~ 27】
for (String boyName : boyhs) {
//boyName依次表示每一个男生的名字
int age = r.nextInt(10) + 18;
list.add(boyName + "-男-" + age);
}
//4.生成女生的信息并添加到集合当中
//【18 ~ 25】
for (String girlName : girlhs) {
//girlName依次表示每一个女生的名字
int age = r.nextInt(8) + 18;
list.add(girlName + "-女-" + age);
}
return list;
}
}
2、随机点名器
2.1、练习1:普通随机点名
2.2、练习2:加入了概率和统计
2.3、练习3:作弊功能
2.4、练习4:随机不能重复,自动开启第二轮
2.5、练习5:带权重的随机
package com.yaqi.myiotest6;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws IOException {
//1.把文件中所有的学生信息读取到内存中
ArrayList<Student> list = new ArrayList<>();
BufferedReader br = new BufferedReader(new FileReader("myiotest\\src\\com\\itheima\\myiotest6\\names.txt"));
String line;
while((line = br.readLine()) != null){
String[] arr = line.split("-");
Student stu = new Student(arr[0],arr[1],Integer.parseInt(arr[2]),Double.parseDouble(arr[3]));
list.add(stu);
}
br.close();
//2.计算权重的总和
double weight = 0;
for (Student stu : list) {
weight = weight + stu.getWeight();
}
//3.计算每一个人的实际占比
//[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
double[] arr = new double[list.size()];
int index = 0;
for (Student stu : list) {
arr[index] = stu.getWeight() / weight;
index++;
}
//4.计算每一个人的权重占比范围
for (int i = 1; i < arr.length; i++) {
arr[i] = arr[i] + arr[i - 1];
}
//5.随机抽取
//获取一个0.0~1.0之间的随机数
double number = Math.random();
//判断number在arr中的位置
//二分查找法
//方法回返回: - 插入点 - 1
//获取number这个数据在数组当中的插入点位置
int result = -Arrays.binarySearch(arr, number) - 1;
Student stu = list.get(result);
System.out.println(stu);
//6.修改当前学生的权重
double w = stu.getWeight() / 2;
stu.setWeight(w);
//7.把集合中的数据再次写到文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\src\\com\\itheima\\myiotest6\\names.txt"));
for (Student s : list) {
bw.write(s.toString());
bw.newLine();
}
bw.close();
}
}
javabean
package com.yaqi.myiotest6;
public class Student {
private String name;
private String gender;
private int age;
private double weight;
public Student() {
}
public Student(String name, String gender, int age, double weight) {
this.name = name;
this.gender = gender;
this.age = age;
this.weight = weight;
}
/**
* 获取
*
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
*
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
*
* @return gender
*/
public String getGender() {
return gender;
}
/**
* 设置
*
* @param gender
*/
public void setGender(String gender) {
this.gender = gender;
}
/**
* 获取
*
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
*
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
*
* @return weight
*/
public double getWeight() {
return weight;
}
/**
* 设置
*
* @param weight
*/
public void setWeight(double weight) {
this.weight = weight;
}
public String toString() {
return name + "-" + gender + "-" + age + "-" + weight;
}
}
3、登录注册
3.1、练习1:写一个登录小案例
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) throws IOException {
/*
需求:写一个登陆小案例。
步骤:
将正确的用户名和密码手动保存在本地的userinfo.txt文件中。
保存格式为:username=zhangsan&password=123
让用户键盘录入用户名和密码
比较用户录入的和正确的用户名密码是否一致
如果一致则打印登陆成功
如果不一致则打印登陆失败
*/
//1.读取正确的用户名和密码
BufferedReader br = new BufferedReader(new FileReader("myiotest\\src\\com\\yaqi\\myiotest7\\userinfo.txt"));
String line = br.readLine();//username=zhangsan&password=123
br.close();
String[] userInfo = line.split("&");
String[] arr1 = userInfo[0].split("=");
String[] arr2 = userInfo[1].split("=");
String rightUsername = arr1[1];
String rightPassword = arr2[1];
//2.用户键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//3.比较
if(rightUsername.equals(username) && rightPassword.equals(password)){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
}
}
3.2、练习2:添加锁定账号功能
与练习1的区别
package com.yaqi.myiotest8;
import java.io.*;
import java.util.Scanner;
public class Test {
public static void main(String[] args) throws IOException {
/*
需求:写一个登陆小案例(添加锁定账号功能)
步骤:
将正确的用户名和密码手动保存在本地的userinfo.txt文件中。
保存格式为:username=zhangsan&password=123&count=0
让用户键盘录入用户名和密码
比较用户录入的和正确的用户名密码是否一致
如果一致则打印登陆成功
如果不一致则打印登陆失败,连续输错三次被锁定
*/
//1.读取正确的用户名和密码
BufferedReader br = new BufferedReader(new FileReader("myiotest\\src\\com\\yaqi\\myiotest8\\userinfo.txt"));
String line = br.readLine();//username=zhangsan&password=123&count=0
br.close();
String[] userInfo = line.split("&");
String[] arr1 = userInfo[0].split("=");
String[] arr2 = userInfo[1].split("=");
String[] arr3 = userInfo[2].split("=");
String rightUsername = arr1[1];
String rightPassword = arr2[1];
//count:表示用户连续输错的次数
int count = Integer.parseInt(arr3[1]);
//2.用户键盘录入用户名和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.nextLine();
System.out.println("请输入密码");
String password = sc.nextLine();
//3.比较
if (rightUsername.equals(username) && rightPassword.equals(password) && count < 3) {
System.out.println("登陆成功");
writeInfo("username=" + rightUsername + "&password=" + rightPassword + "&count=0");
} else {
count++;
if (count < 3) {
System.out.println("登陆失败,还剩下" + (3 - count) + "次机会");
} else {
System.out.println("用户账户被锁定");
}
writeInfo("username=" + rightUsername + "&password=" + rightPassword + "&count=" + count);
}
}
/*
* 作用:
* 写出一个字符串到本地文件中
* 参数:
* 要写出的字符串
* */
public static void writeInfo(String content) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\src\\com\\yaqi\\myiotest8\\userinfo.txt"));
bw.write(content);
bw.close();
}
}
3.3、练习3:补全拼图小游戏的登录注册(考虑多个用户)
导入项目:先将模块文件夹复制到你想要导入到的项目文件夹中,然后通过文件结构中的添加模块将该模块导入
打开界面时就通过IO来读取用户信息,且该代码需要写在构造方法中
Ⅰ、登录
示例代码1:读取本地文件中的用户信息 —— 登录
//读取本地文件中的用户信息
private void readUserInfo() {
//1.读取数据
List<String> userInfoStrList = FileUtil.readUtf8Lines("E:\\ideaProjects\\basic-code\\puzzlegame\\userinfo.txt");
//2.遍历集合获取用户信息并创建User对象
for (String str : userInfoStrList) {
//username=zhangsan&password=123
String[] userInfoArr = str.split("&");
//0 username=zhangsan 1 password=123
String[] arr1 = userInfoArr[0].split("=");
String[] arr2 = userInfoArr[1].split("=");
User u = new User(arr1[1],arr2[1]);
allUsers.add(u);
}
System.out.println(allUsers);
}
Ⅱ、注册
示例代码2:读取本地文件中的用户信息 —— 注册
重置:清空三个输入框
else if(e.getSource() == reset){
//点击了重置按钮
//清空三个输入框
username.setText("");
password.setText("");
rePassword.setText("");
注册:
/*
* 作用:
* 判断username在集合中是否存在
* 参数:
* 用户名
* 返回值:
* true:存在
* false:不存在
*
* */
public boolean containsUsername(String username){
for (User u : allUsers) {
if(u.getUsername().equals(username)){
return true;
}
}
return false;
}
if(e.getSource() == submit){
//点击了注册按钮
//1.用户名,密码不能为空
if(username.getText().length() == 0 || password.getText().length() == 0 || rePassword.getText().length() == 0){
showDialog("用户名和密码不能为空");
return;
}
//2.判断两次密码输入是否一致
if(!password.getText().equals(rePassword.getText())){
showDialog("两次密码输入不一致");
return;
}
//3.判断用户名和密码的格式是否正确
if(!username.getText().matches("[a-zA-Z0-9]{4,16}")){
showDialog("用户名不符合规则");
return;
}
if(!password.getText().matches("\\S*(?=\\S{6,})(?=\\S*\\d)(?=\\S*[a-z])\\S*")){
showDialog("密码不符合规则,至少包含1个小写字母,1个数字,长度至少6位");
return;
}
//4.判断用户名是否已经重复
if(containsUsername(username.getText())){
showDialog("用户名已经存在,请重新输入");
return;
}
//5.添加用户
allUsers.add(new User(username.getText(),password.getText()));
//6.写入文件
FileUtil.writeLines(allUsers,"E:\\ideaProjects\\basic-code\\puzzlegame\\userinfo.txt","UTF-8");
//7.提示注册成功
showDialog("注册成功");
//关闭注册界面,打开登录界面
this.setVisible(false);
new LoginJFrame();
4、游戏的存档和读档
4.1、存档
Ⅰ、在菜单中添加“存档”和“读档”
Ⅱ、点击“存档后”,将游戏数据写到本地
创建GameInfo.java
4.2、读档
4.3、修改bug
bug1:刚打开游戏界面时,存档和读档都是空的
解决方法:在initJMenuBar()方法中添加getGameInfo方法
5、游戏配置
5.1、配置文件的优点
5.2、常见的配置文件
5.3、properties配置文件
5.4、Properties作为Map集合的操作
package com.yaqi.myiotest9;
import java.util.Properties;
public class Test1 {
public static void main(String[] args) {
/*
Properties作为Map集合的操作
*/
//1.创建集合的对象
Properties prop = new Properties();
//2.添加数据
//细节:虽然我们可以往Properties当中添加任意的数据类型,但是一般只会往里面添加字符串类型的数据
prop.put("aaa","111");
prop.put("bbb","222");
prop.put("ccc","333");
prop.put("ddd","444");
//3.遍历集合
/*Set<Object> keys = prop.keySet();
for (Object key : keys) {
Object value = prop.get(key);
System.out.println(key + "=" + value);
}*/
/* Set<Map.Entry<Object, Object>> entries = prop.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
Object key = entry.getKey();
Object value = entry.getValue();
System.out.println(key + "=" + value);
}*/
}
}
5.5、Properties跟IO流结合的操作(store)
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class Test2 {
public static void main(String[] args) throws IOException {
/*
Properties跟IO流结合的操作
*/
//1.创建集合
Properties prop = new Properties();
//2.添加数据
prop.put("aaa","bbb");
prop.put("bbb","ccc");
prop.put("ddd","eee");
prop.put("fff","iii");
//3.把集合中的数据以键值对的形式写到本地文件当中
FileOutputStream fos = new FileOutputStream("myiotest\\a.properties");
prop.store(fos,"test");
fos.close();
/*BufferedWriter bw = new BufferedWriter(new FileWriter("myiotest\\a.properties"));
Set<Map.Entry<Object, Object>> entries = prop.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
Object key = entry.getKey();
Object value = entry.getValue();
bw.write(key + "=" + value);
bw.newLine();
}
bw.close();*/
}
}
5.6、读取Properties(load)
package com.yaqi.myiotest9;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Test3 {
public static void main(String[] args) throws IOException {
//1.创建集合
Properties prop = new Properties();
//2.读取本地Properties文件里面的数据
FileInputStream fis = new FileInputStream("myiotest\\a.properties");
prop.load(fis);
fis.close();
//3.打印集合
System.out.println(prop);
}
}
5.7、拼图游戏的配置文件
4、每日一记(IO的最终大作业)