1 IO流对象
IO : Input Output IO作用是将数据从一个设备中流入到另一个设备。
数据文件,从磁盘中流向内存中 , 从磁盘中流向移动存储设备 , 从一台计算机流向另一台计算机。
一切都是字节 : 任何数据文件都是字节组成, 字节是计算机中最小的存储单元 (Java源码,游戏,音乐,电影)。
2 IO流对象的分类
2.1 按照操作的文件类型分类
文本类型文件 – 选择流对象字符流
什么是文本文件 : 使用文本工具,记事本,notepad++ ,editplus 打开文件后人类可以直接阅读
非文本类型文件 – 选择流对象字节流
2.2 按照数据的流向分类
输入流 : Java程序从其它地方读取数据
输出流 : Java程序中的数据,写入到其它地方
2.3 IO流对象的分类归纳
字节输出流 : OutputStream 抽象类
字节输入流 : InputStream 抽象类
字符输出流 : Writer 抽象类
字符输入流 : Reader 抽象类
3 字节输出流
java.io.OutputStream是所有字节输出流的超类 : 可以写入任何类型文件
写入字节的方法 write
void write(int b) 写入单个字节
void write(byte[] b)写入字节数组
void write(byte[] b,int off,int len) 写入数组的一部分,开始索引,写入的个数
3.1 FileOutputStream
构造方法 : FileOutputStream(File file)
构造方法 : FileOutputStream(String file)
创建字节输出流对象,绑定参数就是要写入的数据目的
JVM很聪明 : 任何一个操作系统都具备IO的能力, JVM依赖操作系统实现IO功能,IO流对象使用完毕后,要释放资源
3.2 字节输出流写入文件的步骤
创建字节输出流对象,构造方法中,绑定文件路径,写入目的
调用流对象的方法write写入数据
释放资源
public static void writeByteArray() throws IOException{
//创建字节输出流对象 构造方法中,绑定文件路径,写入目的
FileOutputStream fos = new FileOutputStream("D:/1.txt");
byte[] bytes = {97,98,99,100};
//写入字节数组
fos.write(bytes);
//写入字节数组中文
fos.write("你好,我好,大家好".getBytes(StandardCharsets.UTF_8));
//写入数组一部分
fos.write(bytes,0,2);
//释放资源
fos.close();
}
public static void main(String[] args) throws IOException{
//writeByte();
writeByteArray();
}
3.3 追加写入和换行
追加写入, FileOutputStream构造方法的第二个参数写true
换行写入, 使用Windows系统的换行符号 \r\n
3.4 IO异常处理
/**
* try catch异常处理 : close()写在finally
*/
public static void write2() {
//提升作用域 : try外定义变量,try创建对象
FileOutputStream fos = null;
FileOutputStream fos2 = null;
try {
//创建字节输出流对象,构造方法中,绑定文件路径,写入目的
fos = new FileOutputStream("c:/1.txt");
fos2 = new FileOutputStream("c:/2.txt");
//写入单个字节
fos.write(45);
fos.write(49);
fos.write(48);
fos.write(48);
}catch (IOException ex){
ex.printStackTrace();
}finally {
//释放资源
try {
//流对象创建失败,fos变量的值是空,不能调用close
if(fos != null)
fos.close();
}catch (IOException ex){
ex.printStackTrace();
}
//释放资源
try {
//流对象创建失败,fos变量的值是空,不能调用close
if(fos2 != null)
fos2.close();
}catch (IOException ex){
ex.printStackTrace();
}
}
}
4 字节输入流
java.io.InputStream是所有字节输入流的超类 : 可以读取任何类型文件
读取字节的方法 read()
int read() 读取单个字节, 读取到流的末尾返回 -1
int read(byte[] b)读取字节数组 , 读取到流的末尾返回 -1
4.1 FileInputStream
构造方法 : FileInputStream(File file)
构造方法 : FileInputStream(String file)
创建字节输入流对象,绑定参数就是要读取的数据源文件
例如,读取字节数组:
public static void readByteArrary() throws IOException{
FileInputStream fis = new FileInputStream("D:/1.txt");
byte[] bytes = new byte[1024*5]; //字节数组推荐大小为1024的整数倍
//定义一个变量 保存read方法的返回值
int r = 0;
//读取文件,传递字符数组
while ((r=fis.read(bytes))!=-1){
System.out.print(new String(bytes,0,r));
}
fis.close();
}
5 文件复制
实现文件的复制功能,操作系统中的Ctrl+C,Ctrl+V一样, 原理上就是字节搬家。
public static void copy_1() throws IOException {
//字节流输入,绑定数据源文件
FileInputStream fis = new FileInputStream("C:/Users/Acer/Pictures/Acer/p1.jpg");
//字节流输出,绑定要复制的目的文件
FileOutputStream fos = new FileOutputStream("D:/p1.jpg");
//字节缓冲数组
byte[] bytes = new byte[1024];
//定义变量 保存读取方法read的返回值
int r = 0;
//循环读取数据源文件
while ((r=fis.read(bytes))!=-1){
//用字节输出流 写入字节数组 0索引开始,写入读取到的个数
fos.write(bytes,0,r);
}
fis.close();
fos.close();
}
6 字节流的缓冲流(更高效)
使用字节流的缓冲流,提高原有流对象的读写性能
字节流缓冲区流,流的本质上也是字节流
BufferedOuputStream 继承OutputStream
方法write() 写入单个的字节,或者字节数组
BufferedInputStream 继承InputStream
方法read()读取单个字节,读取字节数组
public static void copy_2() throws IOException{
//字节流输入,绑定数据源文件
FileInputStream fis = new FileInputStream("C:/Users/Acer/Pictures/Acer/p1.jpg");
//字节流输出,绑定要复制的目的文件
FileOutputStream fos = new FileOutputStream("D:/p1.jpg");
//创建字节输入流的缓冲流,提高原有字节输入流的效率
BufferedInputStream bis = new BufferedInputStream(fis);
//创建字节输出流的缓冲流 提高原有字节输出流的效率
BufferedOutputStream bos = new BufferedOutputStream(fos);
//字节缓冲数组
byte[] bytes = new byte[1024];
//定义变量 保存读取方法read的返回值
int r = 0;
while ((r=bis.read(bytes))!=-1){
bos.write(bytes,0,r);
}
//关闭流 当使用缓冲流的时候,只需要关闭缓冲流即可(缓冲流会自动关闭基础流)
bis.close();
bos.close();
}
7 字符流
只能操作文本文件
Writer类,是所有字符输出流的父类 (写入文本文件)
write(int c)写入单个字符
write(char[] ch)写入字符数组
write(char[] ch,int off,int len)写入字符数组一部分,开始索引,写入的个数
write(String str)写入字符串
void flush() 刷新该流的缓冲 (写入数据,先写入到内存), 只有刷新了数据才会到达目的文件
Reader类,是所有字符输入流的父类 (读取文本文件)
int read()读取单个字符
int read(char[] ch)读取字符数组
7.1 OutputStreamWriter类
OutputStreamWriter继承Writer,是字符的输出流,同时又是转换流
字符流 = 字节流 + 编码表
OutputStreamWriter 转换流 : 字符流通向字节流的桥梁, 字符转成字节
构造方法:
OutputStreamWriter(OutputStream out)传递任意字节输出流
OutputStreamWriter(OutputStream out,String 编码表名)传递任意字节输出流
转换流写入字符文件,UTF-8编码
7.2 InputStreamReader
InputStreamReader继承Reader,字符输入流,读取文本文件
字节流通向字符流的桥梁, 字节流转成了字符流
构造方法:
InputStreamReader(InputStream out)传递任意字节输入流
InputStreamReader(InputStream out,String 编码表名)传递任意字节输入流
7.3 便捷类
FileWriter 继承 OutputStreamWriter
是字符的输出流,写入文本文件
直接采用默认的编码表
FileWriter构造方法直接传递字符串的文件名即可
FileReader 继承 InputStreamReader
是字符的输入流,读取文本文件
直接采用默认的编码表
FileReader构造方法直接传递字符串的文件名即可
7.4 字符输出流的缓冲流
BufferedWriter : 字符流的缓冲流,继承Writer,写入文本文件
特殊的方法 : newLine() 写入文本换行符,平台无关性
构造方法: BufferedWriter(Writer w)可以传递任意字符输出流
7.5 字符输入流的缓冲流
BufferedReader : 字符流的缓冲流,继承Reader,读取文本文件
特殊的方法 :String readLine() 读取文本一行,平台无关性
构造方法: BufferedReader (Reader r)可以传递任意字符输入流
8 打印流
PrintStream : 字节输出流
PrintWriter : 字符输出流
打印流特性 :
打印流负责输出打印,不关心数据源
方便的打印各种形式数据
打印流永远不会抛出IOException
具有自动刷新
9 对象的序列化
对象的序列化的意义 : 对象变成一个文件,在网络中传递,可以让任何一个人使用。
ObjectOutputStream 对象的序列化
构造方法ObjectOutputStream(OutputStream out)传递字节输出流
void writeObject(Object o)写入对象
/**
* @author summer
* @date 2021/12/8 15:27
* @Description 实现接口,启用序列化
*/
public class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public static void writeObj() throws IOException {
//创建字节输出流,绑定文件
FileOutputStream fos = new FileOutputStream("D:/person.txt");
//对象的序列化流创建
ObjectOutputStream oos = new ObjectOutputStream(fos);
//oos流,写入对象
Person p = new Person("张三",20);
oos.writeObject(p);
oos.close();
}
ObjectInputStream 对象的反序列化
构造方法ObjectInputStream (InputStream out)传递字节输入流
Object readObject()读取对象
/**
* 对象的反序列化
*/
public static void readObj() throws Exception{
//创建字节输入流,读取数据文件,源文件必须是序列化后的文件
FileInputStream fis = new FileInputStream("D:/person.txt");
//创建反序列化对象
ObjectInputStream ois = new ObjectInputStream(fis);
//读取对象
Object object = ois.readObject();
System.out.println(object);
ois.close();
}