缓冲流
缓冲流概述
- 缓冲流也称为高效流,或者高级流。之前学习的字节流可以称为原十六
- 作用:缓冲流自带缓冲区,可以提高原始字节流,字符流读写数据的性能
缓冲流的作用:缓冲流自带缓冲区,可以提高原始字节流、字符流读写数据的性能
字节缓冲流
字节缓冲流的优化原理:
- 字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能比较好
- 字节缓冲输出流自带了8KB缓冲池,数据就直接写到缓冲池中去,写数据性能极高了
public static void main(String[] args) {
//不需要释放资源,小括号里面自动释放资源
try (
//1.创建1个字节与管道相通
InputStream is=new FileInputStream("file-io-app//src//data.txt");
//a.把原始的字节输入流包装成高级的缓冲字节输入流
InputStream bis=new BufferedInputStream(is);
//2.创建一个字节输出流管道与目标文件接通
OutputStream os=new FileOutputStream("file-io-app//src//data1.txt");
//b.把字节输出流管道包装成高级缓冲字节输出流管道
OutputStream bos=new BufferedOutputStream(os);
){
//3.定义一个字节数组转移数据
byte[] buffer=new byte[1024];
int len;//记录每个数据读取的字节数
while((len=bis.read(buffer))!=-1){
bos.write(buffer,0,len);
}
System.out.println("复制完了");
} catch (Exception e) {
e.printStackTrace();
}
}
字节缓冲流的性能分析
用复制视频来分析
public class ByteBufferTimeDemo {
public static final String SRC_FILE="D:\\Download\\Java入门基础视频教程,java零基础自学首选黑马程序员Java入门教程(含Java项目和Java真题)_P172_05、线程同步、同步代码块、同步方法、同步锁_分段1.flv";
public static final String DESC_FILE="D:\\code\\";//这里的文件名不要写死,会导致四部操作都复制到同一个文件中
public static void main(String[] args) {
//copy01();//使用低级字节流按照一个一个字节的形式复制文件:慢的让人简直无法忍受。淘汰
copy02();//使用低级字节流按照一个一个字节数组的形式复制文件。比较慢,但是可以忍受
copy03();//缓冲流一个一个字节复制
copy04();//缓冲流一个一个字节数组赋值:飞快 简直不要太快(推荐)
}
/**
* 使用低级的字符按照一个一个字节的形式复制文件
*/
private static void copy01() {
long statTime=System.currentTimeMillis();
try (
InputStream is=new FileInputStream(SRC_FILE);
OutputStream os=new FileOutputStream(DESC_FILE+"copy01.flv");
){
int c;
while ((c=is.read())!=-1){
os.write(c);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("使用低级的字符按照一个一个字节的形式复制文件"+(endTime-statTime)/1000.0+"s");
}
/**
* 使用低级字节流按照一个一个字节数组的形式复制文件
*/
private static void copy02() {
long statTime=System.currentTimeMillis();
try (
InputStream is=new FileInputStream(SRC_FILE);
OutputStream os=new FileOutputStream(DESC_FILE+"copy02.flv");
){
byte[] buffer=new byte[1024];
int len;//记录每次读取的字节数
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("使用低级字节流按照一个一个字节数组的形式复制文件"+(endTime-statTime)/1000.0+"s");
}
/**
* 缓冲流一个一个字节复制
*/
private static void copy03() {
long statTime=System.currentTimeMillis();
try (
//1.创建1个字节与管道相通
InputStream is=new FileInputStream(SRC_FILE);
//a.把原始的字节输入流包装成高级的缓冲字节输入流
InputStream bis=new BufferedInputStream(is);
//2.创建一个字节输出流管道与目标文件接通
OutputStream os=new FileOutputStream(DESC_FILE+"copy03.flv");
//b.把字节输出流管道包装成高级缓冲字节输出流管道
OutputStream bos=new BufferedOutputStream(os);
){
int c;
while ((c=bis.read())!=-1){
bos.write(c);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("使用缓冲的字符按照一个一个字节的形式复制文件"+(endTime-statTime)/1000.0+"s");
}
private static void copy04() {
long statTime=System.currentTimeMillis();
try (
//1.创建1个字节与管道相通
InputStream is=new FileInputStream(SRC_FILE);
//a.把原始的字节输入流包装成高级的缓冲字节输入流
InputStream bis=new BufferedInputStream(is);
//2.创建一个字节输出流管道与目标文件接通
OutputStream os=new FileOutputStream(DESC_FILE+"copy04.flv");
//b.把字节输出流管道包装成高级缓冲字节输出流管道
OutputStream bos=new BufferedOutputStream(os);
){
byte[] buffer=new byte[1024];
int len;//记录每次读取的字节数
while ((len=bis.read(buffer))!=-1){
bos.write(buffer,0,len);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("使用缓冲字节流按照一个一个字节数组的形式复制文件"+(endTime-statTime)/1000.0+"s");
}
}
综上:建议使用字节缓冲输入流、字节缓冲输出流,结合数组的方式,目的前来看是性能最优的组合
字符缓冲流
字符缓冲输入流:BufferedReader
作用:提高字符输入流读取数据的性能,除此之外多了按照多了按照读取数据的功能
/**
* 目标学会缓冲字符输入流提高字符输入流的性能,新增了按照读取的方法(经典代码)
*/
public class BufferedReaderDemo1 {
public static void main(String[] args) {
try (
Reader fr=new FileReader("file-io-app\\src\\data.txt");
BufferedReader br=new BufferedReader(fr);
){
// char[] buffer=new char[1024];
// int len;
// while ((len=fr.read(buffer))!=-1){
// String rs=new String(buffer,0,len);
// System.out.println(rs);
// }
//如果空行下面没有行就都null
String line;
while ((line=br.readLine())!=null)
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符缓冲输出流:BufferedWriter
作用:提高字符输出流写数据的性能,除此之外多了换行的功能
**
* 目标:缓冲字符输出流的使用,学会他多出来一个功能,newLine()
*/
public class BufferedWriterDemo2 {
public static void main(String[] args) throws Exception {
//1.创建一个字符输出流管与目标文件接通
Writer fw=new FileWriter("file-io-app\\src\\data.txt",true);
//覆盖管道,每次启动都会清空文件之后的数据
BufferedWriter bw=new BufferedWriter(fw);
bw.write('a');
bw.write('c');
bw.newLine();//bw.write("\r\n");
bw.write("adasda",0,5);
}
}
案例
需求:把《出师表》的文章顺序进行回复发哦一个新文件中
转换流
字符输入转换流
之前使用字符流读取数据没有乱码,因为代码和文件编号都是UTF-8,但是如果代码便哈和文件编码不一致,使用字符流直接读取会乱码。
可以使用字符输入转换流解决这个问题。
可以提取文件BGK的原始字节流,原始字节不会存在问题
然后把字节流以指定编码转换成字符输入流,这样字符输入流中的字符就不会乱码了
public static void main(String[] args) throws Exception {
InputStream is=new FileInputStream("ss");
//2.把原始字节流转换成字符输入流
Reader isr=new InputStreamReader(is,"GBK");//就是这一句
BufferedReader br=new BufferedReader(isr);
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
字符输出转换流
可以把字符以指定变化获取字节后再使用字节输出流写出去"我爱你中国.getBytes(编码)"
。也可以使用字符输出转换流实现
序列化对象
对象序列化
作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化
使用到的流是对象字节输出流:ObjectOutPutStream(把低级字节输出流包装成高级的对象字节输出流)
/**
* 目标:学会对象序列华,使用ObjecOutStream把内存中的都西昂存入到磁盘文件中
* 对象如果一定要序列化,那就一定要实现一个接口
*/
public class ObjectOutputStreamDemo1 {
public static void main(String[] args) throws IOException {
//创建学生对象
Student s=new Student("小米","chenlei","123333",21);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("file-io-app/src/data.txt"));
//3.直接使用序列化法
oos.writeObject(s);
//4.释放资源
oos.close();
}
}
/**
* 如果需要序列化,就一定要是实现Serializable接口
*/
public class Student implements Serializable {
private String name;
private String loginName;
private String passWord;
private int age;
public Student() {
}
public Student(String name, String loginName, String passWord, int age) {
this.name = name;
this.loginName = loginName;
this.passWord = passWord;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", loginName='" + loginName + '\'' +
", passWord='" + passWord + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
对象反序列化
对象反序列化使用到的流是对象字节输入流:ObjectInputStream
作用:以内存为基准,把存储到文件中去的对象数据恢复成内存中的对象,称为对象反序列化
public class ObjectInputStreamDemo {
public static void main(String[] args) throws Exception {
ObjectInputStream is=new ObjectInputStream(new FileInputStream("file-io-app/src/data.txt"));
Student s=(Student) is.readObject();
System.out.println(s);
}
}
/**
* 如果需要序列化,就一定要是实现Serializable接口
*/
public class Student implements Serializable {
//申明徐磊画的版本好
//序列化的版本好与反序列化的版本好必须一致猜不会出错!
private static final long seriaVersionUID=1;
private String name;
private String loginName;
private transient String passWord;//transient修饰的成员变量不参与序列化,返回的是null
private int age;
打印流
作用:打印流可以实现方便、高校的打印数据到文件中去。打印流一般是指:PrintStream,PrintWriter两个类
可以实现打印什么数据就是什么数据,例如打印整数97写出去就是97,打印boolean的true,写出去就是true
- PrintStream
public class PrintDemo1 {
public static void main(String[] args) throws Exception {
//PrintStream ps=new PrintStream("file-io-app/src/data.txt");//之前的数据会被清空
PrintStream ps=new PrintStream(new FileOutputStream("file-io-app/src/data.txt",true));//这样才是最佳数据
ps.println(97);
ps.println('a');
ps.println(true);
ps.println("我是答应输出流的,我是啥就打印啥");
ps.close();
}
}
- 打印流有几种?各有什么特点
- 打印流一般指:PrintStream,PrintWrite两个类
- 打印功能2者是一样的使用方式
- PrintStream继承自字节输出流OutputStream,支持写字节
- PrintWrite继承自字节输出流Writer,支持写字符 - 打印的优势是什么
- 两者在打印功能都是使用方便,性能高校(核心优势)
public static void main(String[] args) throws Exception {
System.out.println("拆迁办一个");
System.out.println("发生发射点");
//改变输出语句的位置
PrintStream ps=new PrintStream("file-io-app/src/data.txt");
System.setOut(ps);
System.out.println("撒大啊大大是");
System.out.println("士大夫首发式");
}
补充知识:Properties
- Properties属性级对象
其实就是一个Map集合
核心作用:代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去
属性文件:后缀是.properties结尾的文件,里面的内容都是key=value,后续做系统配置信息
public class PropertiesDemo1 {
public static void main(String[] args) throws Exception {
Properties properties=new Properties();
properties.setProperty("admin","1212");
System.out.println(properties);
properties.store(new FileWriter("file-io-app/src/data.txt"),"this is just a comments");
}
}
补充知识:IO框架
public static void main(String[] args) throws Exception {
//1.完成文件复制
IOUtils.copy(new FileInputStream("D:\\我的文件\\证书及成绩单\\蓝桥杯1.jpg"),new FileOutputStream("D:\\我的文件\\copy.jpg"));
//完成文件复制到某个文件夹下
FileUtils.copyFileToDirectory(new File("D:\\我的文件\\证书及成绩单\\蓝桥杯1.jpg"),new File("D:\\我的文件"));
//完成某个文件夹复制到某个文件夹下,可以创建不存在的文件夹
FileUtils.copyDirectoryToDirectory(new File("D:\\我的文件\\证书及成绩单"),new File("D:\\new"));
}