一、理解:
1. 简单而言:流就是内存与存储设备之间传输数据的通道、管道
2. 流的分类:
(1) 按方向 ( 以 JVM 虚拟机为参照物 ) 【重点】
输入流:将< 存储设备 > 中的内容读入到 < 内存 > 中
输出流:将< 内存 > 中的内容写入到 < 存储设备 > 中
(2) 按单位:
字节流:以字节为单位,可以操作所有类型的文件
字符流:以字符为单位,只能操作文本类型的文件
按功能:
节点流:具有基本的读写功能
过滤流:在节点流的基础上,增加新的功能
二、字节流:
1. 字节流的父类(抽象类)
(1) InputStream :字节输入流
对应的操作为读操作
功能方法:read 方法
(2) OutputStream: 字节输出流
对应的操作为写操作
功能方法:write 方法
2. 文件字节节点流
(1) FileOutputStream :文件字节输出流
构造方法:
FileOutputStream fos = new FileOutputStream("D:/test34/a.txt");
参数:操作的文件路径,如果指定的文件不存在,jvm 自动创建一个新的;但是如果指定的文件夹不存在,则运行报错,错误信息为:java.io.FileNotFoundException(文件路径找不到异常 )
路径:绝对路径和相对路径
绝对路径:盘符:\\ 路径 ....
相对路径:默认在当前项目中查找指定的路径
FileOutputStream fos = new FileOutputStream("file/b.txt");
功能方法:
write(int a):将单个字节内容写入到文件中
close():关闭流,释放资源
(2) FileInputStream: 文件字节输入流
构造方法:
FileInputStream fis = new FileInputStream("file/c.txt");
参数:操作文件路径,如果指定的文件或是文件夹不存在,则运行时报错,错误信息为:
java.io.FileNotFoundException(文件路径找不到异常)
功能方法:
int read():一次读取一个字节的内容,将读取的内容作为返回值进行返回,如果达到文件的尾部, 则返回-1
3. 字节过滤流
(1) BufferedOutputStream/BufferedInputStream
缓冲流, 提高 IO 效率,减少访问磁盘的次数;
数据存储在缓冲区中,flush 是将缓存区的内容写入文件中,也可以直接 close 。
// 创建文件字节输入流和输出流
FileInputStream fis = new FileInputStream("D:\\test\\ph.mp4");///读文件
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("file/ph_copy.mp4");// 写文件
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 2. 边读边写
while(true){
int n=bis.read();// 读
if(n==-1) break;
bos.write(n); // 写
}
// 关闭流:释放资源
bis.close();
bos.close();
(2) 过滤流: ObjectOutputStream/ObjectInputStream
a.增强了缓冲区功能
b. 增强了读写 8 种基本数据类型和字符串功能
c. 增强了操作对象的功能:
writeObject(Object obj):写对象
Object obj=readObject():读对象
d. 对象序列化:对象在流上传输的过程
要求:参与对象序列化的对象对应的类,必须实现java.io.Serializable接口 ( 空接口 / 标记接口 )
transient修饰的属性,不参与对象序列化
对象序列化达到文件尾部的标识:如果运行时抛出 java.io.EOFException,代表读取的文件达到尾部
对象序列化的细节:如果对象的属性,是自定义类型的对象时,则该对象也必须是可序列化的
案例:
public class TestObjectOutputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException
{
Student s = new Student("王思浩",36,99.0);
// 将学生对象写入到文件中
// 1. 创建文件字节输出流对象
FileOutputStream fos = new FileOutputStream("file/stu.txt");
// 2. 包装过滤流:增强读写操作
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 3. 写对象
oos.writeObject(s);
// 4. 关闭流
oos.close();
// 从文件中读取对象: 输入流
FileInputStream fis = new FileInputStream("file/stu.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj=ois.readObject();
System.out.println(obj);
ois.close();
}
}
三、字符流
1. 字符流的父类(抽象类):
(1) Reader :字符输入流
对应的操作为读操作
功能方法:read 方法
(2) Writer: 字符输出流
对应的操作为写操作
功能方法:write 方法
2. 文件字符输入/输出流
(1) FileWriter 文件字符输出流,继承 Writer 中的方法:
public void write(int n):将单个字符写入到文件中
(2) FileReader 文件字符输入流,继承 Reader 中的方法:
public int read():一次读取一个字符的内容
3. 字符过滤流
(1) BufferedReader :增强读取一行内容的方法
String readLine(): 一次性读取一行内容,返回值为 String ,达到文件尾部时,返回 null
(2) PriterWriter :一次性写入一行内容
println(String str):将一行内容写入到文件,自动换行
print(String str):将一行内容写入到文件,不自动换行
4. 桥转换流
InputStreamReader 、 OutputStreamWriter
(1) 字符流和字符流之间转换的通道
(2) 指定编解码格式
public class TestInputStreamReader {
public static void main(String[] args) throws IOException {
// 1. 创建文件字节输入流对象( 基础流 ) -> 不能更改文件编码格式 (GBK)
FileInputStream fis = new FileInputStream("file/m.txt");
// 2. 创建桥转换流,指定编解码格式为 "GBK"
InputStreamReader isr = new InputStreamReader(fis,"GBK");
// 3. 包装过滤流:增强读操作
BufferedReader br = new BufferedReader(isr);
// 4. 读操作
while(true){
String s = br.readLine();
if(s==null) break;
System.out.println(s);
}
// 5. 关闭流
br.close();
}
}
package testio2;
import java.io.*;
public class TestInputStreamReader {
public static void main(String[] args) {
BufferedReader br = null;
try {
// 1. 创建文件字节输入流对象(基础流 ) -> 不能更改文件编码格式 (GBK)
FileInputStream fis = new FileInputStream("file/m.txt");
// 2. 创建桥转换流,指定编解码格式为 "GBK"
InputStreamReader isr = new InputStreamReader(fis, "GBK");
// 3. 包装过滤流:增强读操作
br = new BufferedReader(isr);
// 4. 读操作
while (true) {
String s = br.readLine();
if (s == null) break;
System.out.println(s);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(br!=null){
// 5. 关闭流
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}