缓冲流
昨天学习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流。比如能够高效读写的缓冲流,能够
转换编码的转换流,能够持久化存储对象的序列化流等等。这些功能更为强大的流,都是在基本的流对象基础之上
创建而来的,就像穿上铠甲的武士一样,相当于是对基本流对象的一种增强。
1.1 概述
缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:
字节缓冲流: BufferedInputStream , BufferedOutputStream
字符缓冲流: BufferedReader , BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO
次数,从而提高读写的效率。
缓冲流原理:
1.2 字节缓冲输出流
package com.itheima.demo01.BufferedStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
java.io.BufferedOutputStream extends OutputStream
BufferedOutputStream:字节缓冲输出流
继承自父类的共性成员方法:
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
public abstract void write(int b) :将指定的字节输出流。
构造方法:
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。
参数:
OutputStream out :字节输出流
我们可以传递FileOutputStream,缓冲流会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率
int size:指定缓冲流内部缓冲区的大小,不指定默认
使用步骤:
1.创建一个字节输出流FileOutputStream,构造方法中绑定要输出的目的地
2.创建BufferOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream对象效率
3.使用BufferedOutputStream对象中的方法writer,把数据写入到内部缓冲区中
4.使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据,刷新到文件中
5.释放资源(会先调用flush方法刷新数据,第四部可以省略)
*/
public class Demo01BufferedOutputStream {
public static void main(String[] args) throws IOException {
//1.创建一个字节输出流FileOutputStream,构造方法中绑定要输出的目的地
FileOutputStream fos = new FileOutputStream("10_IOPlus\\a.txt");
//2.创建BufferOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream对象效率
BufferedOutputStream bos = new BufferedOutputStream(fos);
//3.使用BufferedOutputStream对象中的writer,把数据写入到内部缓冲区中
bos.write("我把数据写入到内部缓冲区中".getBytes());
//4.使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据,刷新到文件中
bos.flush();
//5.释放资源(会先调用flush方法刷新数据,第四部可以省略)
bos.close();
}
}
1.3字节缓冲输入流
package com.itheima.demo01.BufferedStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
/*
java.io.BufferedInputStream extends InputStream
BufferedInputStream:字节缓冲输入流
继承自父类的成员方法:
public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
public abstract int read() : 从输入流读取数据的下一个字节。
public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
构造方法:
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
BufferedInputStream(InputStream in, int size) 创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。
参数:
InputStream in :字节输入流
我们可以传递FileOutputStream,缓冲流会给FileInputStream增加一个缓冲区,提高FileInputStream的读取效率
int size:
指定缓冲流内部缓冲区大小,不指定默认
使用步骤:
1.创建一个字节输出流FileInputStream,构造方法中绑定要输出的目的地
2.创建BufferInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象效率
3.使用BufferedInputStream对象中的方法read,读取文件
4.释放资源
*/
public class Demo02BufferedInputStream {
public static void main(String[] args) throws IOException {
//1.创建一个字节输出流FileInputStream,构造方法中绑定要输出的目的地
FileInputStream fis = new FileInputStream("10_IOPlus\\a.txt");
//2.创建BufferInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象效率
BufferedInputStream bis = new BufferedInputStream(fis);
//3.使用BufferedInputStream对象中的方法read,读取文件
/*
//int read()从输入流中读取数据的下一个字节
int len = 0;
while((len = bis.read())!=-1){
System.out.println(len);
}
*/
//int read(byte[] b)从输入流中读取一定数量的字节 ,并将其存储在缓冲区数组b中
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
//4.释放资源
bis.close();
}
}
1.4使用缓冲字节流复制文件
使用数组的方式,代码如下:
1.5字符缓冲输出流
package com.itheima.demo01.BufferedStream;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/*
java.io.BufferedWriter extends Writer
BufferedWriter:字符缓冲输出流
继承自父类的共性成员方法:
void write(int c) 写入单个字符。
void write(char[] cbuf) 写入字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
void write(String str) 写入字符串。
void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
void flush() 刷新该流的缓冲。
void close() 关闭此流,但要先刷新它
构造方法:
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
参数:
Writer out :字符输出流
我们可以传递FileWriter,缓冲流会给FileWriter增加一个缓冲区,提高FileWriter的写入效率
int sz : 指定缓冲区的大小,不写默认大小
特有的成员方法:
void newLine() 写一个行分隔符。 会根据不同的操作系统,获取不同的行分隔符
写换行:写换行符号
windows:\r\n
linux:/n
mac:/r
使用步骤:
1.创建一个字节输出流FileWriter,构造方法中绑定要输出的目的地
2.创建BufferWriter对象,构造方法中传递FileWriter对象,提高FileWriter对象效率
3.使用BufferedWriter对象中的方法writer,把数据写入到内部缓冲区中
4.使用BufferedWriter对象中的方法flush,把内存缓冲区中的数据,刷新到文件中
5.释放资源(会先调用flush方法刷新数据,第四部可以省略)
*/
public class Demo03BufferedWriter {
public static void main(String[] args) throws IOException {
//1.创建一个字节输出流FileWriter,构造方法中绑定要输出的目的地
FileWriter fw = new FileWriter("a.txt");
//2.创建BufferWriter对象,构造方法中传递FileWriter对象,提高FileWriter对象效率
BufferedWriter bw = new BufferedWriter(fw);
//3.使用BufferedWriter对象中的方法writer,把数据写入到内部缓冲区中
for (int i = 0; i < 10; i++) {
bw.write("传智播客");
// bw.write("\r\n");
bw.newLine();
/*
System.out.println();
public void println() {
newLine();
}*/
}
//4.使用BufferedWriter对象中的方法flush,把内存缓冲区中的数据,刷新到文件中
bw.flush();
//5.释放资源(会先调用flush方法刷新数据,第四部可以省略)
bw.close();
}
}
1.6字符缓冲输入流
package com.itheima.demo01.BufferedStream;
/*
java.io.BufferedReader extends Reader
BufferedReader:字符缓冲输入流
继承自父类的共性成员方法:
public void close() :关闭此流并释放与此流相关联的任何系统资源。
public int read() : 从输入流读取一个字符。
public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
构造方法:
BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) 创建一个新的缓冲字符输入流,使用给定大小的输入缓冲区。
参数:
Reader in :字符输入流
我们可以传递FileReader,缓冲流会给FileReader增加一个缓冲区,提高FileReader的写入效率
int sz : 指定缓冲区的大小,不写默认大小
特有的成员方法:
String readLine() 读一行文字。读一行文字。
一行被视为由换行符('\ n'),回车符('\ r')中的任何一个或随后的换行符终止。
返回值:包含行的内容的字符串,不包括任何行终止字符,如果已达到流的末尾,则为null
使用步骤:
1.创建一个字节输入流FileReader,构造方法中绑定要输入的目的地
2.创建BufferReader对象,构造方法中传递FileReader对象,提高FileReader对象效率
3.使用BufferedReader对象中的方法read/readLine,把数据写入到内部缓冲区中
4.使用BufferedReader对象中的方法flush,把内存缓冲区中的数据,刷新到文件中
5.释放资源(会先调用flush方法刷新数据,第四部可以省略)
*/
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Demo04BufferedReader {
public static void main(String[] args) throws IOException {
//
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String str;
while ((str = br.readLine()) != (null)) {
System.out.println(str);
}
br.close();
}
}
1.7使用HashMap/缓冲流对文本进行排序练习
package com.itheima.demo01.BufferedStream;
import java.io.*;
import java.util.HashMap;
/*
练习:
对文件的内容进行排序
按照(1,2,3)顺序排序
in.txt:
4.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1.xxxxxxxxxxxxxxxxxxxx
5.xxxxxxxxxxxxxxx
分析:
1.创建一个HashMap集合对象,可以:存储每行文本的序号,value:存储每行的文本
2.创建字符缓冲输入流对象,构造方法中绑定字符输入流
3.创建字符缓冲输出流对象,构造方法中绑定字符输出流
4.使用字符缓冲输入流中的方法readLine,逐行读取文本
5.对读取的文本进行切割,获取行中的序号和文本内容
6.把切割好的序号和文本的内容存储到HashMap集合中,(key序号是有序的,会自动排序1,2,3)
7.遍历HashMap集合,获取每一个键值对
8.把每一个键值对拼接为文本行
9.把拼接好的文本,使用字符缓冲输出流中的方法write,写入到文本中
10.释放资源
*/
public class Demo05Test {
public static void main(String[] args) throws IOException {
//1.创建一个HashMap集合对象,可以:存储每行文本的序号,value:存储每行的文本
HashMap<String,String> map = new HashMap<>();
//2.创建字符缓冲输入流对象,构造方法中绑定字符输入流
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
//3.创建字符缓冲输出流对象,构造方法中绑定字符输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("ou.txt"));
//4.使用字符缓冲输入流中的方法readLine,逐行读取文本
String line;
while((line=br.readLine())!=null){
//5.对读取的文本进行切割,获取行中的序号和文本内容
String [] array = line.split("\\.");
//6.把切割好的序号和文本的内容存储到HashMap集合中,(key序号是有序的,会自动排序1,2,3)
map.put(array[0],array[1]);
}
//7.遍历HashMap集合,获取每一个键值对
for (String key:map.keySet()) {
String value = map.get(key);
//8.把每一个键值对拼接为文本行
line = key+"."+value;
//9.把拼接好的文本,使用字符缓冲输出流中的方法write,写入到文本中
bw.write(line);
bw.newLine();
}
//10.释放资源
bw.close();
br.close();
}
}