写在前面,考试周结束了,短暂的休息后继续学习!
I/O框架
什么是流
- 概念:内存与存储设备之间传输数据的通道。
- 程序在内存中,文件在硬盘中,要建立两者联系的通道,这一通道就是流,没有这个通道(流),内存中的程序就无法交互硬盘中的文件。

- 水借助管道传输;数据借助流传输。
流的分类
-
按方向【重点】:
以内存为参照物
- 输入流:将<存储设备>中的内容读入到<内存>中。
- 输出流:将<内存>中的内容写入到<存储设备>中。

-
按单位:
- 字节流:以字节为单位,可以读写所有数据。
- 字符流:以字符为单位,只能读写文本数据。
-
按功能:
- 节点流(底层流):具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
字节流
-
字节流的父类(抽象类)为流的读写提供基本操作:
-
InputStream:字节输入流
- public int read(){}
- public int read(byte[] b){}
- public int read(byte[] b,int off, int len){}
-
OutputStream:字节输出流
- public void write(int n){}
- public void write(byte[] b){}
- public void write(byte[] b,int off,int len){}
-
-
InputStream


- OutputStream


文件字节流
- FileInputStream:
- public int read(byte[] b) // 从流中读取多个字节,将读取的内容存入b数组,返回实际独到的字节数;如果达到文件的尾部,则返回-1。
- FileOutputStream
- public void write(byte[] b) // 一次写多个字节,将b数组中所有字节,写入输出流。
1.FileInputStream



2.FileOutputStream
FileInputStream
package io;
import java.io.FileInputStream;
/**
* FileInputStream的使用
* 文件字节输入流
*/
public class Demo01 {
public static void main(String[] args) throws Exception {
// 1.创建FileInputStream,并指定文件路径
FileInputStream fis = new FileInputStream("d:aaa.txt");
// 2.读取文件
// fis.read(); 读取一个字节
// 2.1 单个字节读取 效率低
// int date = 0;
// while((date = fis.read()) != -1) {
// // 不进行强制转换会得到字符的ASCII码值(int类型)
// System.out.print((char) date + " ");
// }
// 2.2 多个字节读取 数组开多大一次就能读多少位
byte[] buf = new byte[1024];
// 初始化读取字符的个数
int count = 0;
// read()读完返回值为-1,,所以条件是不为-1就接着读
while ((count = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
// 3.关闭
fis.close();
System.out.println("执行完毕");
}
}
结果:
luck1yliu@foxmail.com 中文能读吗?能
执行完毕
FileOutputStream
package io;
import java.io.FileOutputStream;
/**
* FileOutputStream的使用
* 文件字节输出流
*/
public class Demo02 {
public static void main(String[] args) throws Exception {
// 1.创建文件字节输出流对象
FileOutputStream fos = new FileOutputStream("d:\\bbb.txt",false); // true则不会覆盖前面写的文件
// 2.写入文件
// fos.write(97);
// fos.write('b');
// fos.write('c');
String string = "false会覆盖";
fos.write(string.getBytes());
// 3.关闭
fos.close();
System.out.println("执行完毕");
}
}
FileOutputStream fos = new FileOutputStream("d:\\bbb.txt",true);
结果:
false会覆盖false会覆盖
FileOutputStream fos = new FileOutputStream("d:\\bbb.txt",false);
结果:
false会覆盖
字节流复制文件
package io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 使用文件字节流实现文件的复制
*/
public class Demo03 {
public static void main(String[] args) throws Exception {
// 1.创建流
// 1.1文件字节输入流
FileInputStream fis = new FileInputStream("D:\\testpic.jpeg");
// 1.2文件字节输出流
FileOutputStream fos = new FileOutputStream("D:\\testpic2.jpeg");
// 2.一边读取一边写入
byte[] buf = new byte[1024];
int count = 0;
while ((count = fis.read(buf)) != -1) {
fos.write(buf, 0, count);
}
// 3.关闭
fis.close();
fos.close();
System.out.println("复制完毕");
}
}
结果:

字节缓冲流
- 缓冲流:BufferedInputStream/BufferedOutputStream
- 提高IO效率,减少访问磁盘的次数
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。
- 缓存区中有要读取的数据,则不用再去硬盘读取了,提高效率。
读取
package io;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
/**
* 使用字节缓冲流读取
* BufferedInputStream
*/
public class Demo04 {
public static void main(String[] args) throws Exception {
// 1.创建BufferedInputStream
FileInputStream fis = new FileInputStream("d:\\aaa.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// 2.读取
// int data = 0;
// while ((data = bis.read()) != -1) {
// System.out.print((char) data);
// }
// 2.1自行创建缓冲区
byte[] buf = new byte[1024];
int count = 0;
while((count = bis.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
// 3.关闭
// 用 BufferedInputStream 时,关闭其对象会自动关闭 FileInputStream 对象。
bis.close();
}
}
结果:

luck1yliu@foxmail.com 如果是字符串呢 如果是字符串(new String)就能读出来
写入
package io;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
/**
* 使用字节缓冲流写入文件
* BufferedOutputStream
*/
public class Demo05 {
public static void main(String[] args) throws Exception {
// 1.创建字节输出缓冲流
FileOutputStream fos = new FileOutputStream("d:\\ccc.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 2.写入文件
for (int i = 0; i < 10; i++) {
bos.write("helloworld\r\n".getBytes()); // 写入缓冲区
bos.flush(); // 刷新到硬盘
}
// 3.关闭
bos.close(); // 关闭时,内部也会调用flush方法,将之前的数据一次性刷新,但可能会数据丢失
}
}
结果:

对象流
- 对象流:ObjectOutputStream/ObjectInputStream
- 增强了缓冲区功能
- 增强了读写8中基本数据类型和字符串功能
- 增强了读写对象的功能:
- readObject() 从流中读取一个对象
- writeObject(Object obj) 向流中写入一个对象
- 使用流传输对象的过程称为序列化、反序列化。
- 序列化:将内存中的对象写入硬盘
- 反序列化:从硬盘中读取对象到内存中
实现对象的序列化
需要在类里实现接口 Serializable : 标记接口,作用是说明这个类可以实例化,其实Serializable里面什么方法都没有 。
package io;
import java.io.Serializable;
/**
* 学生类
*/
public class Student implements Serializable {
/**
* 序列化版本号ID,作用是保证序列化的类和反序列化的类是同一个类
*/
private static final long serialVersionUID = 100L;
private String name;
/**
* 使用 transient 修饰属性,则该属性不能被序列化。
*/
private transient