缓冲流的原理:
底层也是使用基本流(FileXxx)来读写
但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高 了程序效率
java.io.BufferedOutputStream类: 缓冲字节输出流
BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流
BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置 缓冲区大小
BufferedOutputStream使用步骤:
1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地
2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象
3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
5.释放资源(会先调用flush方法刷新数据, 第4步可以省略)
缓冲字节输入流: BufferedInputStream
BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲 区大小
使用步骤:
1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象
3.使用BufferedInputStream对象中的方法 read(), 读取文件
4.释放资源 close()
缓冲字符输出流: BufferedWriter
// 构造方法
// 构造方法 BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
//特有方法
void newLine(): 写入一个换行符, 换行符自动根据当前系统确定
文件末尾缓冲字符输入流: BufferedReader
// 构造方法
BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流
BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小
//特有方法
String readLine(): 一次读一行字符串, "不包含换行符". 读到返回null
转换流
乱码原因:读写编码不一致
乱码:
??? 找不到字符
空格 看不见 找不到字符
兯ρ乯 能找到字符, 但是找错了
编码: 字符 -> 字节 'a' -> 97
解码: 字节 -> 字符 97 -> 'a'
java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
// 构造方法
OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
//使用默认的UTF-8
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt")); o.write("dsfdsfdsaf")
// 使用指定的GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
osw.write("你") -> 查"GBK"码表 -> -1,-2 -> FileOutputStream -> a.txt文件
写数据: 字符流 --------------------------> 字节流
InputStreamReader类介绍及使用
InputStreamReader(InputStream in): 使用默认编码表创建转换流
InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "GBK");
'你' <- 查"GBK"码表 <- isr.read() <- -1,-2 <- FileInputStream <- a.txt文件
读数据: 字符流 <---------- 字节流
转换流小结:
FileReader = InputStreamReader + FileInputStream, 按照IDEA中UTF-8将读取的字节转换为字符
FileWriter = OutputStreamWriter + FileOutputStream, 按照IDEA中UTF-8将写出的字符转换为字节
转换流InputStreamReader, OutputStreamWriter在读写时, 可以指定按照哪个编码表来进行转换
字符流 = 编码表 + 字节流
转换流主要用于解决Web开发中的乱码问题
序列化和反序列化
序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中
对象 -> 字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象
字节 -> 对象
通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态
对象序列化流: ObjectOutputStream
ObjectOutputStream(OutputStream out)
void writeObject(Object obj): 将对象写出
对象反序列化流: ObjectInputStream
ObjectInputStream(InputStream in)//构造方法
Object readObject(): 读取对象//特有成员方法
如果将对象序列化到文件中后, 代码中的类发生了变化, 能否正常反序列化文件中的对象?
serialVersionUID序列号的作用:
序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中. 该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化 当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException
为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是一样的
打印流
打印流PrintStream:
PrintStream特点:
1. 只有输出流, 没有输入流
2. PrintStream不会抛出IOException
3. 有特殊方法 print(), println(), 可以输出任意类型的值, 原样输出
java.io.PrintStream类: 字节打印流
//构造方法
PrintStream(File file): 创建字节打印流, 输出到一个文件
PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径
//静态方法
static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流