文章目录
缓冲流
缓冲流概述
缓冲流也称为高效流,或者高级流。之前学习的字节流可以成为原始流。见该文章: Java基础 file、方法递、IO流
作用:缓冲流自带缓冲区,可以提高原始字节流,字符流写数据的性能。
BufferedInputSream 字节缓冲输入流
BufferedOutputSream 字节缓冲输出流
BufferedReader 字符缓冲输入流
BufferedWriter 字符缓冲输出流
字节缓冲流
字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能比较好。
字节流缓冲流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了。
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 使用字节缓冲流完成数据的读写操作
*/
public class ByteBufferDemo {
public static void main(String[] args) {
try (
//这儿里面只能放置资源对象,用完会自动关闭
//自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
// OutputStream os = new FileOutputStream("logback-APP\\\\src\\\\data");//先清空之前的数据,写新的数据
//1. 创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("IO\\data",true);
//a.把原始的字节输入流包装成高级的缓冲字节输入流
OutputStream bos = new BufferedOutputStream(os);
//2.创建一个字节·输入流管道与目标文件接通
//b.把字节输入流管道包装成高级的缓冲字节书入流管道
InputStream is = new FileInputStream("IO\\data01");
InputStream bis = new BufferedInputStream(is);
){
//3.定义一个字节数组用于转移数据
byte [] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = bis.read(buffer))!=-1){
bos.write(buffer,0,len);
}
System.out.printf("复制完成");
os.flush(); //写数据一定要刷新数据
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节缓冲流的性能分析
用于直观感受字节缓冲流的性能
需求:分别使用低级字节流和高级字节缓冲流拷贝大视频,记录耗时
分析:
- 使用低级的字节流按照一个一个字节的形式复制文件
- 使用低级的字节流一个一个字节数组的形式复制文件
- 使用高级的缓冲字节流按照一个一个字节的形式复制文件
- 使用高级的缓冲字节流按照一个一个字节数组的形式复制文件
import java.io.*;
public class ByteBufferTimeDemo {
private static final String SRC_FILE = "D:\\Microsoft Edge Download\\ideaIU-2021.3.2.exe";//文件所在地址
private static final String DEST_FILE = "D:\\Microsoft Edge Download\\";//文件要复制到的地方+后面需要拼接该文件复制到该路径后的名称
public static void main(String[] args) {
// 1. 使用低级的字节流按照一个一个字节的形式复制文件:慢的让人无法忍受
//copy01();
// 2. 使用低级的字节流一个一个字节数组的形式复制文件:比较慢
copy02();
// 3. 使用高级的缓冲字节流按照一个一个字节的形式复制文件:很慢,不建议使用
copy03();
// 4. 使用高级的缓冲字节流按照一个一个字节数组的形式复制文件:很快
copy04();
}
private static void copy04() {
long startTime = System.currentTimeMillis();
try (
//1. 创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE+"video4.exe");
//a.把原始的字节输入流包装成高级的缓冲字节输入流
OutputStream bos = new BufferedOutputStream(os);
//2.创建一个字节·输入流管道与目标文件接通
//b.把字节输入流管道包装成高级的缓冲字节书入流管道
InputStream is = new FileInputStream(SRC_FILE);
InputStream bis = new BufferedInputStream(is);
){
//3.定义一个字节数组用于转移数据
byte [] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = bis.read(buffer))!=-1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用高级的缓冲字节流按照一个一个字节数组的形式复制文件耗时:"+(endTime-startTime)/1000.0+"秒");
}
private static void copy03() {
long startTime = System.currentTimeMillis();
try (
//1. 创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE+"video3.exe");
//a.把原始的字节输入流包装成高级的缓冲字节输入流
OutputStream bos = new BufferedOutputStream(os);
//2.创建一个字节·输入流管道与目标文件接通
//b.把字节输入流管道包装成高级的缓冲字节书入流管道
InputStream is = new FileInputStream(SRC_FILE);
InputStream bis = new BufferedInputStream(is);
){
//3.定义一个变量用于转移数据
int b;//记录每次读取的字节数
while ((b = bis.read())!=-1){
bos.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用高级的缓冲字节流按照一个一个字节的形式复制文件耗时:"+(endTime-startTime)/1000.0+"秒");
}
// //a.把原始的字节输入流包装成高级的缓冲字节输入流
// OutputStream bos = new BufferedOutputStream(os);
//b.把字节输入流管道包装成高级的缓冲字节书入流管道
// InputStream bis = new BufferedInputStream(is);
private static void copy02() {
long startTime = System.currentTimeMillis();
try (
//1. 创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream(DEST_FILE+"video2.exe");
//2.创建一个字节·输入流管道与目标文件接通
InputStream is = new FileInputStream(SRC_FILE);
){
//3.定义一个字节数组用于转移数据
byte [] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = is.read(buffer))!=-1){
os.write(buffer,0,len);
}
System.out.printf("复制完成");
os.flush(); //写数据一定要刷新数据
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用低级的字节流按照一个一个字节数组的形式复制文件耗时:"+(endTime-startTime)/1000.0+"秒");
}
/**
* 使用低级的字节流按照一个一个字节的形式复制文件
*/
private static void copy01() {
long startTime = System.currentTimeMillis();
try (
//1.创建低级的字节输入流和源文件链接
InputStream is = new FileInputStream(SRC_FILE);
//2.创建低级的字节输出流和源文件链接
OutputStream os = new FileOutputStream(DEST_FILE+"video1.exe");
){
//3.定义一个变量记录每次读取的字节(一个一个字节的复制)
int b;
while ((b = is.read())!=-1){
os.write(b);
}
}catch (Exception e){
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用低级的字节流按照一个一个字节的形式复制文件耗时:"+(endTime-startTime)/1000.0+"秒");
}
}
把低级字节流数组的小更改为原来的八倍(高级缓冲字节流自带8KB的缓冲区)
缓冲流采用1KB的字节数组即可
字符缓冲流
字节缓冲输入流:BufferedReader
作用:提高字符输入流读取的性能,除此之外多了按照行读取数据的功能
public ReadLine()
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
public class BufferedReaderDemo {
public static void main(String[] args) {
try(
//1.创建个文件字符输出流与文件接通
Reader fr = new FileReader("IO\\data");
//q.把低级的字符流包装成高级的缓冲流
BufferedReader br = new BufferedReader(fr);
) {
// //2.用循环读取一个字符数组的数据
// int len;
// char[] buffer = new char[1024];
// while((len = br.read(buffer))!=-1){
// System.out.printf(new String(buffer,0,len));
// }
// System.out.printf( br.readLine());
//经典写法:行读很重要
String Line;
while ((Line=br.readLine())!=null){
System.out.println(Line);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
字节缓冲输出流:BufferedWriter
作用:提高字符输出流读取的性能,除此之外多了换行功能
转换流
当代码编码于文件编码不一致时,使用字符流直接读取中文会乱码。
字符流直接读取文本内容,必须文件和代码编码一直才不会出现乱码
字符输入转换流(InputStreamReader)
字符输入转换流:把原始字节流按照指定的编码转换成字符输入流
import java.io.*;
public class inputStreamReaderDemo {
public static void main(String[] args)throws Exception {
//代码UTF-8 文件GBK
//1.提取GBK文件的原始字节流
InputStream is = new FileInputStream("");
//2.把原始字节流转换为字符输入流
//Reader isr = new InputStreamReader(is);//默认以UTF-8的方式转换为字符流,还是会乱码的 跟直接使用FileReader一致
Reader isr = new InputStreamReader(is,"GBK");//以指定的GBK编码转换为字符输入流
BufferedReader br = new BufferedReader(isr);//缓冲流
String line ;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
}
字符输出转换流(OutputStreamWriter)
import java.io.*;
//目标:使用OutputStreamWriter
public class OutputStreamWriterDemo {
public static void main(String[] args) throws Exception {
//1.定义一个字节输出流
OutputStream os = new FileOutputStream("");
//2.把原始字节输出流转换为字符输出流
//Writer osw = new OutputStreamWriter(os);//一默认的方式UTF-8 跟直接写FileRead一样
Writer osw = new OutputStreamWriter(os,"GBK");//指定GBK的方式写字符出去
//3.把低级的字符输出流包装成高级的缓冲字符流
BufferedWriter bw = new BufferedWriter(osw);
bw.write("我爱中国");
bw.close();
}
}
序列化对象
对象序列化
作用:以内存为基准,把内存中的对象存储到磁盘中去,称为对象序列化
对象字节输出流:ObjectOutputStream,写对象数据到数据磁盘中
规定:如果你想将该对象序列化,那么该对象一定要实现Serializable接口
存储结果,并非乱码
import java.io.Serializable;
public class Student {
private String name;
private int age;
private String loginName;
private String passWord;
public Student() {
}
public Student(String name, int age, String loginName, String passWord) {
this.name = name;
this.age = age;
this.loginName = loginName;
this.passWord = passWord;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
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;
}
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", age=" + age +
", loginName='" + loginName + '\'' +
", passWord='" + passWord + '\'' +
'}';
}
}
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws Exception {
//1.创建一个对象
Student s = new Student("晓星尘",23,"xiaoxingchen","123456");
//2.把对象存储
//对象序列化:使用对象字节输出流包装字节输出流管道
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO\\data"));
//3.直接调用序列化方法
oos.writeObject(s);
//4.释放资源
oos.close();
//规定:
//如果你想将该对象序列化,那么该对象一定要实现Serializable接口
}
}
对象反序列化
作用:以内存为基准,把存储到磁盘文件中的对象数据恢复成内存中的对象
对象字节输入流:ObjectInputStream
注意:transient
注意: serialVersionUID
private static final long serialVersionUID:序列化版本号
如果之前序列化版本号serialVersionUID的值为1,对该类的对象进行序列化,在对其序列化得到的文件进行反序列化,可以成功获取该对象
将该序列化版本号serialVersionUID的值改为2,未对其再次进行序列化(之前文件的序列化版本号为1),反序列化(此时反序列化的版本号为2)之前的文件将会出现错误。
序列化的版本号于反序列化的版本号需一致
需对该对象再次进行序列化即可
打印流
作用:打印流可以实现方便,高效的打印数据到文件中去。
可以实现打印什么数据就是什么数据
PrintStream
import java.io.PrintStream;
//打印流写数据高效且方便
//底层实现使用了BufferWriter
public class printDemo {
public static void main(String[] args) throws Exception{
//1.创建一个打印流对象
//PrintStream ps = new PrintStream(new FileOutputStream("")); //可以通向低级管道
PrintStream ps = new PrintStream("IO/data","GBK");//可以直接通向文件 ,可以确定编码
ps.println(97);
ps.println('a');
ps.println("写啥打印啥");
ps.flush();
ps.close();
}
}
PrintWriter
import java.io.PrintWriter;
//打印流写数据高效且方便
//底层实现使用了BufferWriter
//打印上PrintStream与PrintWriter没有区别
public class printDemo {
public static void main(String[] args) throws Exception{
//1.创建一个打印流对象
//PrintWriter ps = new PrintWriter(new FileOutputStream("")); //可以通向低级管道
PrintWriter ps = new PrintWriter("IO/data","GBK");//可以直接通向文件 ,可以确定编码
ps.println(97);
ps.println('a');
ps.println("写啥打印啥");
ps.flush();
ps.close();
}
}
PrintStream与PrintWriter的区别
打印数据功能上是一摸一样的,都是使用方便,性能高效
printStream继承自字节输出流OutputStream,支持写字节数据的方法
PrintWriter继承自字符输出流Writer,支持字符数据的方法
补充知识:Properties
Propeties其实是一个Map集合,一般不会当集合用,核心作用是将Properties代表一个属性文件,可以把对象中的键值对信息存入到一个属性文件中去。
属性文件:后缀是.properties结尾的文件,里面的内容都是key=value,后续做系统配置文件的。
properties和IO流结合的方法
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
public class PropertiesDemo {
public static void main(String[] args) throws Exception{
//需求:使用Properties把键值对存入到属性文件中
Properties properties_writer = new Properties();
properties_writer.setProperty("d","12434");
properties_writer.setProperty("jadk","jsdlks");
/**
* 参数一:保存管道
* 参数二:保存心得
*/
properties_writer.store(new FileWriter("IO\\data02.properties"),"注释");
//_____________________________________________
//需求:使用Properties把键值对从属性文件中读取出来
Properties properties_read = new Properties();
//加载
properties_read.load(new FileReader("IO\\data02.properties"));
System.out.println(properties_read);
}
}
补充知识:IO框架
commons-io概述
commons-io工具包提供了很多关于io操作的类。有两个主要的类FileUtils,IOUtils
commons-io 下载 提取码:xs90
简单使用
导入commons-io-2.6.jar做开发
需求:使用commins-io简化io流读写
分析:
- 在项目中创建一个文件夹lib
- 将commons-io-2.6.jar文件复制到lib文件夹中
- 在jar文件上点击右键,选择Add as Library -> 点击OK
- 在类中导包使用
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class CommonsIODemo {
public static void main(String[] args) throws Exception{
//1.完成文件的复制
// IOUtils.copy(new FileInputStream(""),
// new FileOutputStream(""));
//2.完成文件复制到某个文件夹下
// FileUtils.copyFileToDirectory(new File(""),
// new File(""));
//3.完成文件夹复制到某个文件夹下
// FileUtils.copyDirectoryToDirectory(new File(""),
// new File(""));
//删除文件夹
// FileUtils.delete(new File(""));
}
}