# 目标
- 能够使用字节缓冲流读取数据到程序
- 能够使用字节缓冲流写出数据到文件
- 能够明确字符缓冲流的作用和基本用法
- 能够使用缓冲流的特殊功能
- 能够阐述编码表的意义
- 能够使用转换流读取指定编码的文本文件
- 能够使用转换流写入指定编码的文本文件
- 能够使用序列化流写出对象到文件
- 能够使用反序列化流读取文件到程序中
- 能够使用Properties的load方法加载文件中配置信息
# IO异常的处理
# JDK1.7前处理异常
之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用 try...catch...finally 代码块,处理异常部分。
try {
可能有问题的代码;
} catch (异常类名 变量名) {
处理异常的代码
} finally {
释放资源
}
示例代码:
public static void test01() {
FileWriter fw = null;
try {
fw = new FileWriter("1.txt");
fw.write("abc");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
# JDK1.7及以后处理异常
JDK7增加 try-with-resource 语句来处理资源,该语句确保了每个资源在语句结束时关闭。
try (创建流的代码) {
其他代码;
} catch (IOException e) {
处理异常的代码
}
注意: try() 中的代码不是什么都可以的,主要用来使用的资源的资源管理。
示例代码如下:
public static void test02() {
// 类实现了AutoCloseable接口就能放到try的()中,就会自动关流
try (
FileWriter fw = new FileWriter("study_day12\\abc\\1.txt");
FileReader fr = new FileReader("study_day12\\abc\\2.txt");
) {
fw.write("aaa");
} catch (IOException e) {
System.out.println("处理了IO流异常!");
}
}
# 练习
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
目标:学习IO异常的处理
JDK7以前的处理IO流异常
try {
可能有问题的代码
} catch (异常类名 变量名) {
处理异常的代码
} finally {
关闭流
}
代码繁琐
JDK7处理IO流异常
会自动关闭流
try (创建流的代码) {
可能有问题的代码
} catch (异常类名 变量名) {
处理异常的代码
}
*/
public class Demo {
public static void main(String[] args) {
// JDK1.7 以前的 IO 处理
FileWriter fw = null;
try {
fw = new FileWriter("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt");
fw.write("好好玩呀,真的好开心");
} catch(IOException err) {
System.out.println("处理 IO 异常");
} finally {
if (fw != null) {
try {
fw.close();
} catch(IOException err) {
err.printStackTrace();
}
}
}
// JDK1.7处理IO流异常, 只有实现了AutoCloseable 接口的类才能放入,会自动关闭流
try(
FileWriter fileWriter = new FileWriter("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt");
FileReader fileReader = new FileReader("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt");
) {
fileWriter.write("哈哈哈");
} catch(IOException err) {
err.printStackTrace();
}
}
}
# 缓冲流
# 缓冲流作用
之前我们学到的基本流有:
- 字节流: FileInputStream , FileOutputStream
- 字符流: FileReader , FileWriter
后面我们要学的缓冲流,转换流,对象流等是对基本流的增强。
缓冲流是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:
- 字节缓冲流: BufferedInputStream , BufferedOutputStream
- 字符缓冲流: BufferedReader , BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认 8KB 大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
# 字节缓冲流

今天我们要学的字节缓冲流 API 有:
| 构造器 | 说明 |
|---|---|
| public BufferedInputStream(InputStream in) | 把基本的字节输入流包装成一个字节输入缓冲流,从而提高字节输入流读数据的性能 |
| public BufferedOutputStream(OutputStream out) | 把基本的字节输出流包装成一个字节输出缓冲流,从而提高写数据的性能 |
# 字节流复制文件效率对比
使用字节流四种方式复制文件测试不同方式下的性能情况
需求:使用四种方式复制 "D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt" 到 "D:\\learn\\java\\code\\javaUp\\day11\\doc\\2.txt"
文件1.txt的大小为 4285kb
分析:
字节流四种方式复制文件
基本流读写一个字节
基本流读写一个字节数组
缓冲流读写一个字节
缓冲流读写一个字节数组
代码如下:
package demo03字节流四种复制文件_扩展;
import java.io.*;
/*
目标:使用四种方式复制 "D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt" 到 "D:\\learn\\java\\code\\javaUp\\day11\\doc\\2.txt"
四种方式复制:
基本流读写一个字节
基本流读写一个字节数组
缓冲流读写一个字节
缓冲流读写一个字节数组
小结:
缓冲流读写一个字节比基本流读取一个字节快非常多
缓冲流读写一个字节数组和基本流读取一个字节数组差不多
如果使用读写一个字节时,建议使用缓冲流
如果使用读写一个字节数组,建议使用基本流
*/
public class Demo {
public static void main(String[] args) throws IOException {
long startTime1 = System.currentTimeMillis();
test1();
long endTime1 = System.currentTimeMillis();
System.out.println("基本流读写一个字节:" + (endTime1 - startTime1));
long startTime2 = System.currentTimeMillis();
test2();
long endTime2 = System.currentTimeMillis();
System.out.println("基本流读写一个字节数组:" + (endTime2 - startTime2));
long startTime3 = System.currentTimeMillis();
test3();
long endTime3 = System.currentTimeMillis();
System.out.println("缓冲流读写一个字节:" + (endTime3 - startTime3));
long startTime4 = System.currentTimeMillis();
test4();
long endTime4 = System.currentTimeMillis();
System.out.println("缓冲流读写一个字节数组:" + (endTime4 - startTime4));
}
// 基本流读写一个字节
public static void test1() throws IOException {
// 创建输入流
FileInputStream fileInputStream = new FileInputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt");
// 创建输出流
FileOutputStream fileOutputStream = new FileOutputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\2.txt");
// 循环读写
int b; // 保存读取的数据
while ((b = fileInputStream.read()) != -1) {
fileOutputStream.write(b);
}
// 关闭流
fileOutputStream.close();
fileInputStream.close();
}
// 基本流读写一个字节数组
public static void test2() throws IOException {
// 创建输入流
FileInputStream fileInputStream = new FileInputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt");
// 创建输出流
FileOutputStream fileOutputStream = new FileOutputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\2.txt");
// 循环读写
byte[] buf = new byte[1024 * 8]; // 保存读取的数据
int len; // 保存读取的数量
while ((len = fileInputStream.read(buf)) != -1) {
fileOutputStream.write(buf,0, len);
}
// 关闭流
fileInputStream.close();
fileOutputStream.close();
}
// 缓冲流读写一个字节
public static void test3() throws IOException {
// 创建输入流
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt"));
// 创建输出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\2.txt"));
// 循环读写
int b; // 保存读取的数据
while ((b = bufferedInputStream.read()) != -1) {
bufferedOutputStream.write(b);
}
// 关闭流
bufferedOutputStream.close();
bufferedInputStream.close();
}
// 缓冲流读写一个字节数组
public static void test4() throws IOException {
// 创建输入流
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt"));
// 创建输出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("D:\\learn\\java\\code\\javaUp\\day11\\doc\\2.txt"));
// 循环读写
byte[] buf = new byte[1024 * 8];
int len;
while ((len = bufferedInputStream.read(buf)) != -1) {
bufferedOutputStream.write(buf, 0, len);
}
// 关闭流
bufferedInputStream.close();
bufferedOutputStream.close();
}
}
输出结果:
基本流读写一个字节:66497
缓冲流读写一个字节:174
基本流读写一个字节数组:30
缓冲流读写一个字节数组:20
从上面的输出结果可以看出:
基本流读写一个字节,从文件中读取一个字节到内存,再写一个字节到文件,非常慢
缓冲流读写一个字节,从文件中读取8192个字节到缓冲输入流的内存,再从内存读取一个字节到变量再写8192个字节到文件,比较快
基本流读写一个字节数组,从文件中读取8192个字节到我们自己的数组,再写8192个字节到文件,非常快
缓冲流读写一个字节数组,从文件中读取8192个字节到缓冲输入流的内存,再复制到我们自己的数组再把我们自己的数组8192复制到缓冲字节输出流的内存,再写8192个字节到文件,快
总结:
- 缓冲流读取一个字节比基本流读取一个字节快非常多;
- 缓冲流读取一个字节数组和基本流读取一个字节数组差不多;
如果使用读一个字节时,建议使用缓冲流;如果使用读一个字节数组,建议使用基本流。
# 字符缓冲流及特有方法
字符输出缓冲流:BufferedWriter,继承了Writer, 可以使用父类Writer中的write方法
| 构造器 | 说明 |
|---|---|
| public BufferedWriter(Writer r) | 把基本的字符输出流包装成一个字符输出缓冲流,从而提高字符输出流写数据的性能 |
字符输出缓冲流新增功能
| 方法 | 说明 |
|---|---|
| public String newLine() | 换行 |
字符缓冲输入流:BufferedReader 继承了Reader,可以使用父类Reader中的read方法
| 构造器 | 说明 |
|---|---|
| public BufferedReader(Reader r) | 把基本的字符输入流包装成一个字符输入缓冲流,从而提高字符输入流读数据的性能 |
字符输入缓冲流新增功能
| 方法 | 说明 |
|---|---|
| public String readLine() | 读取一行数据返回,如果读取没有完毕,无行可读返回null |
练习代码如下:
package com.itheima.demo04字符缓冲流;
import java.io.*;
/*
目标:字符缓冲流及特有方法(重点)
讲解:
字符输出缓冲流
字符输入缓冲流
小结:
1.BufferReader特有方法?
readLine() // 读一行, 读取到\r\n结束
2.BufferedWriter特有方法?
newLine() 换行, 相当于write("\r\n");
*/
public class Demo04 {
public static void main(String[] args) throws IOException {
// test01();
test02();
}
/*
BufferedWriter: 缓冲字符输出流, 继承了Writer, 还是使用之前的write写数据
构造方法:
BufferedWriter(Writer out) 创建缓冲字符输出流, 对参数传入的流进行包装加强.
特有方法:
newLine() 换行
*/
public static void test01() throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("study_day11\\abc\\3.txt", true));
bw.write("今天很冷!");
bw.newLine(); // 相当于write(\r\n");
bw.write("明天升温!");
bw.close();
}
/*
BufferedReader: 缓冲字符输入流, 继承了Reader,还是使用read读数据
构造方法:
BufferedReader(Reader in) 创建缓冲字符输入流, 对参数传入的流进行包装加强
特有方法:
readLine() // 读一行, 读取到\r\n结束
*/
public static void test02() throws IOException {
/*BufferedReader br = new BufferedReader(new FileReader("study_day11\\abc\\3.txt"));
String line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
// 读取不到数据返回null
line = br.readLine();
System.out.println(line);*/
BufferedReader br = new BufferedReader(new FileReader("study_day11\\abc\\3.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
# 字符流扩展练习
目标:将文件每一行数据读取放到Map中,= 前面是键,= 后面是值
讲解:
分析:
1.创建缓冲字符输入流
2.创建Map集合
3.循环读取每一行数据
4.使用=分割,存储到Map中,=前面的数据是键,=后面的是值
代码如下:
package demo05字符流扩展练习;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
/*
目标:将文件每一行数据读取放到Map中,= 前面是键,= 后面是值
讲解:
分析:
1.创建缓冲字符输入流
2.创建Map集合
3.循环读取每一行数据
4.使用=分割,存储到Map中,=前面的数据是键,=后面的是值
*/
public class Demo {
public static void main(String[] args) throws IOException {
// 1. 创建缓冲字符输入流
BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\learn\\java\\code\\javaUp\\day11\\doc\\1.txt"));
// 2. 创建 Map 集合
// 报错,不能直接创建 Map 因为 'Map' is abstract; cannot be instantiated
// Map<String, InternalError> stringInternalErrorMap = new Map<>();
// HashMap<String, String> stringStringHashMap = new HashMap<>();
HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
// 3.循环读取每一行数据
String line; // 保存读取到的一行数据
while ((line = bufferedReader.readLine()) != null) {
// 4.使用=分割,存储到Map中,=前面的数据是键,=后面的是值
// line是 name=fang
String[] split = line.split("=");
// stringStringHashMap.put(split[0], split[1]);
// stringIntegerHashMap 接收的第二个参数是 Integer 类型,需要转换
stringIntegerHashMap.put(split[0], Integer.parseInt(split[1]));
}
// 遍历Map
// 1.键找值, 2.键值对
// stringStringHashMap.forEach(new BiConsumer<String, String>() {
// @Override
// public void accept(String key, String value) {
// System.out.println(key + ":::" + value);
// }
// });
// stringStringHashMap.forEach((key, value) -> {
// System.out.println(key + ":::" + value);
// });
stringIntegerHashMap.forEach((key, value) -> {
System.out.println(key + ":::" + value);
});
}
}
# 小结
- 字符缓冲流自带8K缓冲区可以提高基本字符流读写数据的性能
- 说出字符缓冲流的新增功能
# 转换流
# 字符集和字符编码的概念
字符集是一些字符的集合,如:ASCII字符集、ISO-8859-1字符集、GBxxx字符集、Unicode字符集等。
字符编码是字符与数字之间的对应规则。
将字符转成二进制,称为编码。如:使用ASCII编码,将 'b' -> 01100010
将二进制数解析成文字,称为解码。如:使用ASCII编码,将 01100010 -> 'b'
# 字符流读不同编码的文件乱码
需求:分别使用如下两种方式读取文件内容
- 代码编码是UTF-8,文件编码也是UTF-8,使用字符流读取观察输出的中文字符结果。
- 代码编码是UTF-8,文件编码使用GBK,使用字符流读取观察输出的中文字符结果。
中文在GBK编码中占2个字节,中文在UTF-8编码中占3个字节,IDEA默认是UTF-8编码在IDEA中,使用 FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的 UTF-8 编码,所以没有任何问题。但是当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。
为什么会乱码?保存和读取使用了不同的编码。
如何解决乱码?保证读取时的编码和保存的编码是相同的就可以。
# 转换流使用
InputStreamReader 指定编码读取数据
| 方法名 | 说明 |
|---|---|
| InputStreamReader(InputStream in) | 使用默认编码读取数据 |
| InputStreamReader(InputStream in, String charsetName) | 使用指定编码读取数据 |
OutputStreamWriter 指定编码写数据
| 方法名 | 说明 |
|---|---|
| OutputStreamWriter(OutputStream out) | 使用默认编码写数据 |
| OutputStreamWriter(OutputStream out, String charsetName) | 使用指定编码写数据 |
# 转换流案例-转换文件编码
需求:将GBK编码的文本文件,转换为UTF-8编码的文本文件。
分析:
1. 创建输入流InputStreamReader指定GBK读取文件
2. 创建输出流OutputStreamWriter指定UTF-8写文件
3. 循环读写数据
4. 关闭流
操作字符时如何选择流?
- 基本流: FileReader / FileWriter
- 转换流: InputStreamReader / OutputStreamWriter
如果不需要修改编码就使用基本流,使用更简单;如果需要修改编码就使用转换流。
# 对象流
# 对象流的使用
对象流分为两类:
- ObjectOutputStream: 对象输出流
- ObjectInputStream: 对象输入流

对象操作流API
| 构造器 | 说明 |
|---|---|
| ObjectOutputStream(OutputStream out) | 对象输出流,把对象以字节的形式写到文件 |
| public void writeObject(Object obj) | 写一个对象到文件中 |
| ObjectInputStream(InputStream in) | 对象输入流,把写到文件中的对象读到程序中 |
| public Object readObject() | 读取文件中的对象 |
注意:对象流操作的类需要实现 Serializable 接口,否则会出现 NotSerializableException 异常。
# 对象流使用细节
- InvalidClassException: 无效的类异常,原因是保存数据后,修改了类,再读取解决方案:给类添加一个版本号,模仿String类的版本号(serialVersionUID) private static final long serialVersionUID = 42L;
- 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?给该成员变量加 transient 关键字修饰,该关键字标记的成员变量不参与序列化过程
# 打印流
- 作用:打印流可以实现方便、高效的打印数据到文件中去。打印流有:PrintStream,PrintWriter两个类。
- 可以实现原样打印,例如打印整数97写出去就是97,打印boolean的true,写出去就是true。 | 构造器 | 说明 | | --- | --- | | PrintStream(File file) | 创建PrintStream, 指定打印的目的地 | | PrintStream(String fileName) | 创建PrintStream, 指定打印的目的地 | | PrintStream(OutputStream out) | 创建PrintStream, 指定打印的目的地 |
| 方法名 | 说明 |
|---|---|
| print(Xxx x) | 打印数据, 不换行 |
| println(Xxx x) | 打印数据, 换行 |
# 属性集
# Properties作为集合使用

Properties类表示属性集。他是一个特殊的集合,可以结合 IO 流操作。
- Properties实现了Map接口,就是一个双列集合可以存储键值对数据,键和值都是字符串类型。
- Properties可以结合流进行操作,可以把集合中的数据保存到流中,也可以从流中来加载数据。
Properties作为集合的特有方法:
| 方法名 | 说明 |
|---|---|
| Object setProperty(String key, String value) | 添加键和值,键和值都是String类型 |
| String getProperty(String key) | 通过键获取值 |
| Set | 获取所有的键 |
# 代码示例
Properties作为集合使用:
package com.itheima.demo14Properties_重点;
import java.util.Properties;
import java.util.Set;
/*
目标:学习Properties作为集合的使用
讲解:
继承体系
Map
↑ 实现
Hashtable
↑ 继承
Properties
Properties类介绍:
1.Properties实现了Map接口,就是一个双列集合可以存储键值对数据, 键和值都是字符串类型
2.Properties可以结合流进行操作, 可以把集合中的数据保存到流中, 也可以从流中来加载数据
Properties作Map集合的特有方法:
Object setProperty(String key, String value) 添加键值对,修改键值对
String getProperty(String key) 通过键获取值
小结:
Properties是一个Map集合,可以存储键值对数据,键和值都是String类型
*/
public class Demo141 {
public static void main(String[] args) {
Properties pp = new Properties();
System.out.println("添加前pp = " + pp);
// 添加键值对
pp.setProperty("name", "唐僧");
pp.setProperty("age", "23");
pp.setProperty("address", "东土大唐");
System.out.println("添加后pp = " + pp);
// 通过键获取值
String name = pp.getProperty("name");
String age = pp.getProperty("age");
String address = pp.getProperty("address");
String sex = pp.getProperty("sex"); // 键不存在返回null
System.out.println(name + ": " + age + ": " + address + ": " + sex);
// 遍历Properties,使用forEach
pp.forEach((key, value) -> {
System.out.println(key + ": " + value);
});
System.out.println("--------------------------------------");
// 了解: stringPropertyNames() 相当于 keySet() 获取所有的键
Set<String> names = pp.stringPropertyNames();
for (String s : names) {
System.out.println(s);
}
}
}
# Properties和IO流结合使用
Properties 和 IO 流结合的方法:
| 方法名 | 说明 |
|---|---|
| void load(Reader reader) | 从输入字符流读取属性列表(键和值) |
| void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
| void store(Writer writer, String comments) | 将Properties中的键和值写入输出字符流中 |
| void store(OutputStream out, String comments) | 将Properties中的键和值写入输出字节流中 |
属性文件介绍:后缀是.properties结尾,里面的内容一行一个 key=value,后续可以做为软件的配置文件。
# 代码示例
Properties 保存和加载文件数据:
package com.itheima.demo14Properties_重点;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/*
目标:学习Properties保存和加载文件数据
讲解:
Properties和流操作的特有方法:
void store(Writer writer, String comments) 将Properties集合中的键值对保存到流中
Writer writer: 指定保存的目的地
String comments: 注释
void load(Reader reader) 从流中加载数据到Properties对象中
Reader reader: 指定读取的路径
*/
public class Demo142 {
public static void main(String[] args) throws IOException {
// testStore();
testLoad();
}
// Properties属性集保存数据到文件: void store(Writer writer, String comments)
public static void testStore() throws IOException {
Properties pp = new Properties();
pp.setProperty("name", "admin");
pp.setProperty("password", "123456");
pp.store(new FileWriter("study_day11\\abc\\pp.properties"), "数据库信息");
}
// 加载文件中数据到Properties属性集中: void load(Reader reader)
public static void testLoad() throws IOException {
Properties pp = new Properties();
System.out.println("加载前: " + pp);
pp.load(new FileReader("study_day11\\abc\\pp.properties"));
// pp.load(new FileReader("study_day11\\abc\\student.txt"));
System.out.println("加载后: ");
pp.forEach((key, value) -> {
System.out.println(key + ": " + value);
});
}
}
# 装饰模式
# 装饰模式介绍
# 了解装饰模式3个角色
装饰设计模式有3个角色:
# 代码演示装饰模式
package com.itheima.demo15装饰设计模式;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Demo15 {
public static void main(String[] args) throws IOException {
// 创建装饰类, 对蔡徐坤进行包装加强
CaiXuKunWarpper warpper = new CaiXuKunWarpper(new CaiXuKun());
warpper.sing(); // 不变
warpper.dance(); // 加强
warpper.rap(); // 扩展新功能
// 其实我们今天学的这些类基本上都是使用了装饰模式
// BufferedReader br = new BufferedReader(new FileReader("study_day11\\abc\\3.txt"));
// br.read(); // 加强
// br.readLine(); // 扩展新功能
// br.close(); // 不变
}
}
package com.itheima.demo15装饰设计模式;
// 明星接口
public interface Star {
public abstract void sing();
public abstract void dance();
}
package com.itheima.demo15装饰设计模式;
// 原对象
public class CaiXuKun implements Star {
@Override
public void sing() {
System.out.println("蔡徐坤一本正经的唱歌!");
}
@Override
public void dance() {
System.out.println("蔡徐坤一本正经的跳舞!");
}
}
package com.itheima.demo15装饰设计模式;
// 装饰类
public class CaiXuKunWarpper implements Star {
// 拥有蔡徐坤,进行加强或扩展
public Star star;
// 构造器给成员变量赋值
public CaiXuKunWarpper(Star star) {
this.star = star;
}
// 不改变,原样调用
@Override
public void sing() {
star.sing();
}
// 增强功能
@Override
public void dance() {
System.out.println("一边跳舞,一边打篮球");
}
// 扩展新功能
public void rap() {
System.out.println("鸡你太美!");
}
}
# 小结
这章我们主要介绍了一些常用的 IO 流方法,方法比较多,可能有点迷糊,下面这张图列出它们之间的关系:
总结:
package com.itheima.demo16总结;
import java.io.IOException;
/*
能够使用字节缓冲流读取数据到程序
BufferedInputStream类:
int read(): 读取一个字节数据
int read(byte[] buf): 读取一个字节数组的数据
能够使用字节缓冲流写出数据到文件
BufferedOutputStream类
void write(int b): 写一个字节
void write(byte[] bs): 写一个字节数组
能够明确字符缓冲流的作用和基本用法
字符缓冲流的作用: 提高效率,有新功能
字符缓冲流的和基本用法:
字符缓输入缓冲流: new BufferedReader(new FileReader(路径));
字符缓输出缓冲流: new BufferedWriter(new FileWriter(路径));
能够使用缓冲流的特殊功能
BufferedReader:
String readLine(): 读取一行
BufferedWriter:
void newLine(): 换行
能够阐述编码表的意义
让文字对应数字,保存到计算中
能够使用转换流读取指定编码的文本文件
InputStreamReader isr = new InputStreamReader(new FileInputStream("路径"), "编码");
isr.read();
能够使用转换流写入指定编码的文本文件
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("路径"), "编码");
osw.write(文字);
能够使用序列化流写出对象到文件
Person p = new Person("凤姐", 18);
// 1.创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("study_day11\\abc\\persons.txt"));
// 2.写对象到文件
oos.writeObject(p);
// 3.关闭
oos.close();
能够使用反序列化流读取文件对象数据到程序中
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("study_day11\\abc\\persons.txt"));
Object obj = ois.readObject(); // Person obj = (Person) ois.readObject();
System.out.println("obj = " + obj);
ois.close();
能够使用Properties的load方法加载文件中配置信息
Properties pp = new Properties();
pp.load(new FileReader("study_day11\\abc\\pp.properties"));
System.out.println("加载后: ");
pp.forEach((key, value) -> {
System.out.println(key + ": " + value);
});
*/
public class Demo {
public static void main(String[] args) throws IOException {
}
}