IO流
存储和读取数据的解决方案
I:input
O:output
流:像水流一样传输数据
IO流的分类
- 流的方向
- 输入流:读取 (文件 ---> 程序)
- 输出流:写出(程序 ---> 文件)
- 操作文件类型:
- 字节流(所有类型的文件)
- 字符流(纯文本文件(Windows自带的记事本打开能读懂))
IO流体系
字节流 | 字符流 | ||
InputStream | OutputStream | Reader | Writer |
字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
字节流
FileOutputStream:操作本地文件的字节输入流,可以把程序中的数据写到本地文件中
书写步骤:
- 创建字节输出流对象
- 参数是字符串表示的路径或者是File对象都是可以的
- 如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
- 如果文件已经存在,则会清空文件
- 写数据
FileOutputStream写数据的三种方式 方法名称 说明 void write(int b) 一次写一个字节数据 void write(byte[] b) 一次写一个字节数组数据 void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据 - write方法的参数是整数,但是实际上写到本地文件中的数据是整数在ASCII上对应的字符
- 换行写
- windows: \r\n
- Linux : \n
- Mac: \r
- 续写:
- 如果想要续写,打开续写开关即可
- 打开开关位置,创建对象的第二个参数
- 默认false:表示关闭续写,此时创建对象会清空文件
- 手动传递true:表示打开续写,此时创建对象不会清空文件
- 释放资源
- 每次使用完流之后都要释放资源
FileOutputStream:操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来
方法名称 | 说明 |
public int read() | 一次读一个字节数据 |
public int read(byte[] buffer) | 一次读一个字节数组 |
一次读取一个字节数组的数据,每次读取会尽可能把数组装满
- 创建字节输入流对象
- 如果文件不存在,就直接报错
- 读取数据
- 一次读一个字节,读出来的是数据在ASCII码表上对应的数字
- 读到文件末尾了,read方法返回-1
- 释放资源
- 每次使用完后都要释放资源
字符流
底层其实是字节流
字符流 = 字节流 + 字符集
特点:
输入流:一次读一个字节,遇到中文时,一次读多个字节
输出流,底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
使用场景:
对于纯文本文件进行读写操作
FileReader
- 创建对象
- public FileReader(File file) 创建字符输入流关联本地文件
- public FileReader(String pathname) 创建字符输入流关联本地文件
- 读取数据
- public int read() 读取数据,读到末尾返回-1
- public int read(char[] buffer) 读取多个数据,读到末尾返回-1
- 释放资源
- public void close() 释放资源/关流
FileWriter
构造方法 | 说明 |
public FileWriter(File file) | 创建字符输出流关联本地文件 |
public FileWriter(String pathname) | 创建字符输出流关联本地文件 |
public FileWriter(File file,boolean append) | 创建字符输出流关联本地文件,续写 |
public FIleWriter(String pathname,boolean append) | 创建字符输出流关联本地文件,续写 |
成员方法 | 说明 |
void write(int c) | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(String str,int off, int len) | 写出一个字符串的一部分 |
void write(char[] cbuf) | 写出一个字符数组 |
void write(char[] cbuf,int off, int len) | 写出字符数组的一部分 |
- 创建字符输出流对象
- 参数是字符串表示的路径或者File对象都是可以的
- 如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
- 如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关
- 写数据
- 如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符
- 释放资源
- 每次使用完流之后都要释放资源
缓冲流
缓冲流 | |||
字节缓冲流 | 字符缓冲流 | ||
BufferedInputStream (字节缓冲输入流) | BufferedOutputStream(字节缓冲输出流) | BufferedReader(字符缓冲输入流) | BufferedWriter(字符缓冲输出流) |
方法名称 | 说明 |
public BufferedInputStream(InputStream is) | 把基本流包装成高级流,提高读取数据的性能 |
public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
方法名称 | 说明 |
public BufferedReader(Reader r) | 把基本流变成高级流 |
public BufferedWriter(Writer r) | 把基本流变成高级流 |
缓冲流提高性能原理:底层自带了长度为8192的缓冲区,显著提高字节流的读写性能,对于字符流提升不明显,对于字符缓冲流而言关键点是有两个特有方法
字符缓冲输入流特有方法 | 说明 |
public String readLine() | 读取一行,如果没有数据可读,会返回null |
字符缓冲输出流特有方法 | 说明 |
public void newLine() | 跨平台的换行 |
readLine方法在读取的时候,一次读一整行,遇到回车换行结束,但是他不会把回车换行读到内存当中
随用随创建·,什么时候不用说明时候直接关闭
转换流
是字符流和字节流之间的桥梁,字节流想要用字符流中的方法时可以使用转换流
字符转换输入流:InputStreamReader
字符转换输出流:OutputStreamWriter
作用:
- 指定字符集读写数据(JDK11之后已淘汰)
- 字节流想要使用字符流中的方法了
序列化流/对象输出操作流
可以把Java中的对象写到本地文件中
构造方法 | 说明 |
public ObjectOutputStream(OutputStream out) | 把基本流包装成高级流 |
成员方法 | 说明 |
public final void writeObject(Object obj) | 把对象序列化(写出)到文件中去 |
使用对象输出流将对象保存到文件时会出现NotSerializableException异常
解决方案:需要让Javabean类实现Serializable接口(此接口没有抽象方法,标记型接口,一旦实现这个接口。那么表示当前的对象类可以被序列化)
序列化流写到文件中的数据是不能修改的,一旦修改就无法再次读回来了
反序列化流
可以把序列化到本地文件中的对象,读取到程序中来
构造方法 | 说明 |
public ObjectInputStream(InputStream out) | 把基本流变成高级流 |
成员方法 | 说明 |
public Object readObject() | 把序列化到本地文件中的对象,读取到程序中来 |
如果想在修改Javabean类后,再次序列化,不会抛出InvalidClassException异常,需要给Javabean类添加一个版本号:serialVersionUID (用private static final修饰)
如果想让某个成员变量不被序列化,需要给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
打印流
分类:打印流一般是指:PrintStream,PrintWriter两个类
特点1:打印流只操作文件目的地,不操作数据员
特点2:特有的写出方法可以实现,数据原样写出
特点3:特有的写出方法,可以实现自动刷新,自动换行
字节打印流
构造方法 | 说明 |
public PrintStream(OutputStream/File/String) | 关联字节输出流/文件/文件路径 |
public PrintStream(String fileName, Charset charset) | 指定字符编码 |
public PrintStream(OutputStream out, boolean autoFlush) | 自动刷新 |
public PrintStream(OutputStream out, boolean autoFlush,String encoding) | 指定字符编码且自动刷新 |
字节底层没有缓冲区,开不开自动刷新都一样
成员方法 | 说明 |
public void write(int b) | 常规方法:规则跟之前一样,将指定的字节写出 |
public void println(Xxx xx) | 特有方法:打印任意数据,自动刷新,自动换行 |
public void print(Xxx xx) | 特有方法:打印任意数据,不换行 |
public void printf(String format, Object.. args) | 特有方法:带有占位符的打印语句,不换行 |
字符打印流
构造方法 | 说明 |
public PrintWriter(Write/File/String) | 关联字节输出流/文件/文件路径 |
public PrintWriter(String fileName,Charset charset) | 指定字符编码 |
public PrintWriter(Write w,boolean qutoFlush) | 自动刷新 |
public PrintWriter(OutputStream out, boolean autoFlush, Charset charset) | 指定字符编码且自动刷新 |
字符流底层有缓冲区,想要自动刷新需要开启
成员方法 | 说明 |
public void write(...) | 常规方法:规则跟之前一样,将指定的字节写出 |
public void println(Xxx xx) | 特有方法:打印任意数据并且换行 |
public void print(Xxx xx) | 特有方法:打印任意类型的数据,不换行 |
public void printf(String format, Object.. args) | 特有方法:带有占位符的打印语句 |
解压缩流/压缩流
- 解压缩流
- 解压本质:把每一个ZipEntry按照层级拷贝到本地另一个文件夹中
计算机的存储规则
- 在计算机中,任意数据都是以二进制形式存储的
- 八个比特位叫做一个字节,计算机中最小的存储单元是字节
- 简体中文版windows,默认使用GBK字符集
- 英文(GBK)
- ASCII字符集中英文用一个字节存储,兼容ASCII,二进制前面补0
- 汉字(GBK)
- 汉字两个字节存储
- 高位字节二进制一定以1开头,转成十进制之后是一个负数
- Unicode字符集的UTF-8编码格式
- 一个英文占一个字节,二进制第一位是0,转成十进制是正数
- 一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
在Idea外部包使用步骤
- 在项目中创建一个文件夹:lib
- 将jar包复制粘贴到lib文件夹
- 右键点击jar包,选择 Add as Library --> 点击OK
- 在类中导包使用