定义:I表示intput,把硬盘文件中的数据读入到内存的过程,称之输入,负责读;lO表示output,把内存中的数据写出到硬盘文件的过程,称之输出,负责写。
IO流的分类

总结流的四大类
字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流称为字节输入流。
字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流称为字节输出流。
字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流称为字符输入流。
字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流称为字符输出流。

字节流
文件字节输入流:FileInputStream
作用:以内存为基准,把磁盘文件中的数据以字节的形式读取到内存中去
构造器 | 说明 |
---|---|
public FileInputStream(File file) | 创建字节输入流管道与源文件对象接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件路径接通 |
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1 |
public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1 |
// 1、创建一个文件字节输入流管道与源文件连通
InputStream is = new FileInputStream("文件相对路径");
// 2、定义一个字节数组,用于读取字节数组
byte[] buffer = new byte[3];
int len = is.read(buffer);
String rs = new String(buffer);
// String rs = new String(buffer, 0, len); 读取多少倒出多少
System.out.println(rs); //前三个字节代表的内容
// 3、改进使用循环,每次读取一个字节数组
byte[] buffer = new byte[3];
int len;
while((len = is.read(buffer)) != -1){
System.out.print(new String(buffer, 0, len));
}
文件字节输出流:FileOutputStream
作用:以内存为基准,把内存中的数据以字节的形式写出到磁盘文件中去的流
构造器 | 说明 |
---|---|
public FileOutputStream(File file) | 创建字节输出流管道与源文件对象接通 |
public FileOutputStream(File file,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
写数据出去的API
方法名称 | 说明 |
---|---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer , int pos , int len) | 写一个字节数组的一部分出去。 |
- 换行:
os.write(“\r\n”.getBytes())
流的关闭和刷新
方法 | 说明 |
---|---|
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
资源释放的方式
try-catch-finally
finally:放在try-catch后面的,无论是正常执行还是异常执行代码,最后一定要执行,除非JVM退出。
作用:一般用于进行最后的资源释放操作(专业级做法)
格式
try {
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97);
} catch (IOException e) {
e.printStackTrace();
}finally{
// 即使上面有return语句执行,也必须执行完这里才可以!
// 开发中不建议在这加return,加了永远是返回这里的数据
}
JDK 7和JDK9中都简化了资源释放操作

综合案例:文件拷贝
需求:把某个视频复制到其他目录下
import java.io.*;
public class CopyDemo01 {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
// 1、创建一个字节输入流管道与原视频接通
is = new FileInputStream("D:\\原始视频.wmv");
// 2、创建一个字节输出流管道与目标文件接通
os = new FileOutputStream("D:\\new.wmv");
// 3、定义一个字节数组来转移数据
byte[] buffer = new byte[1024];
int len; // 记录每次读取的字节数
while((len = is.read(buffer)) != -1){
os.write(buffer, 0, len);
}
System.out.println("复制完成了!");
// 4、关闭流
os.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
// 无论代码是正常结束,还是出现异常都要最后执行这里
// 4、关闭流
try {
if(os != null) os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(is != null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流
- 读取中文输出,字符流更合适,因为字节流读取中文输出会乱码,或者内存溢出
文件字符输入流:Reader
- 作用:以内存为基准,把磁盘文件中的数据以字符的形式读取到内存中去
构造器 | 说明 |
---|---|
public FileReader(File file) | 创建字符输入流管道与源文件对象接通 |
public FileReader(String pathname) | 创建字符输入流管道与源文件路径接通 |
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字符返回,如果字符已经没有可读的返回-1 |
public int read(char[] buffer) | 每次读取一个字符数组,返回读取的字符个数,如果字符已经没有可读的返回-1 |
文件字符输出流:FileWriter
- 作用:以内存为基准,把内存中的数据以字符的形式写出到磁盘文件中去的流
构造器 | 说明 |
---|---|
public FileWriter(File file) | 创建字符输出流管道与源文件对象接通 |
public FileWriter(File file,boolean append) | 创建字符输出流管道与源文件对象接通,可追加数据 |
public FileWriter(String filepath) | 创建字符输出流管道与源文件路径接通 |
public FileWriter(String filepath,boolean append) | 创建字符输出流管道与源文件路径接通,可追加数据 |
写数据出去的API
方法名称 | 说明 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void write(String str) | 写一个字符串 |
void write(String str, int off, int len) | 写一个字符串的一部分 |
流的关闭和刷新
方法 | 说明 |
---|---|
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
缓冲流
- 缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流
- 作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能
字节缓冲流性能优化原理
- 字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好
- 字节缓冲输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了
字节缓冲流
字节缓冲输入流:BufferedInputStream,提高字节输入流读取数据的性能
字节缓冲输出流:BufferedOutputStream,提高字节输出流读取数据的性能
构造器 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能 |
public BufferedOutputStream(OutputStream os) | 可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
字符缓冲流
- 字符缓冲输入流:BufferedReader,提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能
- 字符缓冲输出流:BufferedWriter,提高字符输出流写取数据的性能,除此之外多了换行功能
构造器 | 说明 |
---|---|
public BufferedReader(Reader r) | 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能 |
public BufferedWriter(Writer w) | 可以把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能 |
字符缓冲流新增功能
方法 | 说明 |
---|---|
public String readLine() | 读取一行数据返回,如果读取没有完毕,无行可读返回null |
public void newLine() | 换行操作 |
转换流
- 作用:解决不同编码读取乱码的问题
- 字符输入转换流:InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流
构造器 | 说明 |
---|---|
public InputStreamReader(InputStream is) | 可以把原始的字节流按照代码默认编码转换成字符输入流,几乎不用,与默认的FileReader一样。 |
public InputStreamReader(InputStream is ,String charset) | 可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了 |
- 字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流
构造器 | 说明 |
---|---|
public OutputStreamWriter(OutputStream os) | 可以把原始的字节输出流按照代码默认编码转换成字符输出流,几乎不用。 |
public OutputStreamWriter(OutputStream os,String charset) | 可以把原始的字节输出流按照指定编码转换成字符输出流 |
序列化对象
对象序列化
- 作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化
- 使用到的流是对象字节输出流:ObjectOutputStream
构造器 | 说明 |
---|---|
public ObjectOutputStream(OutputStream out) | 把低级字节输出流包装成高级的对象字节输出流 |
方法名称 | 说明 |
---|---|
public final void writeObject(Object obj) | 把对象写出去到对象序列化流的文件中去 |
对象反序列化
- 作用:以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象,称为对象反序列化
- 使用到的流是对象字节输入流:ObjectInputStream
构造器 | 说明 |
---|---|
public ObjectInputStream(InputStream out) | 把低级字节输如流包装成高级的对象字节输入流 |
方法名称 | 说明 |
---|---|
public Object readObject() | 把存储到磁盘文件中去的对象数据恢复成内存中的对象返回 |
注意事项
- 对象如果要序列化,必须实现Serializable序列化接口
- transient修饰的成员变量不会参与序列化,这样可以避免泄露敏感信息
- 使用
private static final long serialVersionUID = 1
来申明序列化的版本号码,这样序列化的版本号与反序列化的版本号必须一致才不会出错
打印流
作用:打印流可以实现方便、高效的打印数据到文件中去。打印流一般是指:PrintStream,PrintWriter两个类
可以实现打印什么数据就是什么数据,例如打印整数97写出去就是97,打印boolean的true,写出去就是true
PrintStream
构造器 | 说明 |
---|---|
public PrintStream(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintStream(File f) | 打印流直接通向文件对象 |
public PrintStream(String filepath) | 打印流直接通向文件路径 |
方法 | 说明 |
---|---|
public void print(Xxx xx) | 打印任意类型的数据出去 |
PrintWriter
构造器 | 说明 |
---|---|
public PrintWriter(OutputStream os) | 打印流直接通向字节输出流管道 |
public PrintWriter (Writer w) | 打印流直接通向字符输出流管道 |
public PrintWriter (File f) | 打印流直接通向文件对象 |
public PrintWriter (String filepath) | 打印流直接通向文件路径 |
方法 | 说明 |
---|---|
public void print(Xxx xx) | 打印任意类型的数据出去 |
PrintStream和PrintWriter的区别
打印数据功能上是一模一样的,都是使用方便,性能高效(核心优势)
PrintStream继承自字节输出流OutputStream,支持写字节数据的方法
PrintWriter继承自字符输出流Writer,支持写字符数据出去
输出语句重定向
- 属于打印流的一种应用,可以把输出语句的打印位置改到文件
PrintStream ps = new PrintStream("文件地址");
System.setOut(ps);
Properties
- 其实就是一个Map集合,但是我们一般不会当集合使用,因为HashMap更好用
Properties核心作用
Properties代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去
属性文件:后缀是.properties结尾的文件,里面的内容都是 key=value,后续做系统配置信息的
Properties和IO流结合的方法(API)
构造器 | 说明 |
---|---|
void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
void store(OutputStream out, String comments) | 将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流 |
void store(Writer writer, String comments) | 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流 |
public Object setProperty(String key, String value) | 保存键值对(put) |
public String getProperty(String key) | 使用此属性列表中指定的键搜索属性值 (get) |
public Set<String> stringPropertyNames() | 所有键的名称的集合 (keySet()) |
IO框架
commons-io概述
commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率
commons-io工具包提供了很多有关io操作的类。有两个主要的类FileUtils,IOUtils
FileUtils主要有如下方法
方法名 | 说明 |
---|---|
String readFileToString(File file, String encoding) | 读取文件中的数据, 返回字符串 |
void copyFile(File srcFile, File destFile) | 复制文件。 |
void copyDirectoryToDirectory(File srcDir, File destDir) | 复制文件夹。 |
案例:导入commons-io-2.6.jar做开发
需求:使用commons-io简化io流读写
具体步骤:
- 在项目中创建一个文件夹:lib
- 将commons-io-2.6.jar文件复制到lib文件夹
- 在jar文件上点右键,选择 Add as Library -> 点击OK
- 在类中导包使用