缓冲流:
缓冲流 也叫做高效流 是对4格基本的FileXxx流的增强
字节缓冲流:BufferedInputStream,BufferedOutputStream
字符缓冲流: BufferedReader,BufferedWriter
缓冲流的基本原理 是在创建流对象时 会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写 减少系统IO次数 从而提高读写效率
字节缓冲流:
构造方法:
public BufferedInputStream(Inputstream in):创建一个新d缓冲输入流
public BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流
代码示例:
//创建字节缓冲输入流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("bis.txt"));
//创建字节缓冲输出流
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("bos.txt"));
为什么说通过缓冲区读写能提高读写效率呢? 我测试了一下
通过基本流复制一个大文件(300MB);
//记录开始时间 long start =System.currentTimeMillis(); //创建流对象 try(FileInputStream fis=new FileInputStream(
new FileInputStream("jdk8.exe")); FileOutputStream fos=new FileOutputStream(
new FileOutputStream("copy.exe"));){ //读写数据 int b; while((b=fis.read())!=-1){ fos.write(b); } }catch (IOException e){ e.printStackTrace(); } //结束时间 long end=System.currentTimeMillis(); System.out.println("复制流时间:"+(end-start)+"毫秒");
使用缓冲高效流同样复制一个300MB文件
//记录开始时间 long start=System.currentTimeMillis(); //创建流对象 try(BufferedInputStream bis=new BufferedInputStream(
new FileInputStream("jdk8.exe")); BufferedOutputStream bos=new BufferedOutputStream(
new FileOutputStream("copy.exe")); ){ //读写数据 int b; while ((b=bis.read())!=-1){ bos.write(b); } }catch (IOException e){ e.printStackTrace(); } //记录结束时间 long end=System.currentTimeMillis(); System.out.println("缓冲流复制时间:"+(end-start)+"毫秒");
使用数组的方式 重写缓冲高效流
//记录开始时间 long start=System.currentTimeMillis(); //创建流对象 try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream( "jdk8.exe")); BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream( "jdk8.exe")); ){ //读写数据 int b; byte[] bytes=new byte[8*1024]; while ((b=bis.read(bytes))!=-1){ bos.write(bytes,0,b); } }catch (IOException e){ e.printStackTrace(); } //记录结束时间 long end=System.currentTimeMillis(); System.out.println("缓冲流复制时间:"+(end-start)+"毫秒");
对比请自行进行 这里就不贴结果了
字符缓冲流
构造方法:
public BufferedReader(Reader in):创建一个 新的缓冲输入流
public BufferedWriter(Writer out):创建一个新的缓冲输出流
代码示例:
//创建字符缓冲输入流
BufferedReader br=new BufferedReader(new FileReader("br.txt"));
//创建字符缓冲输出流
BufferedWriter bw=new BuffereWriter(new FileWriter("bw.txt"));
缓冲字符流特有方法:
BufferedReader:public String readLine():读一行文字
BufferedWriter:public void newLine():写一行行分隔符 由系统属性定义符号
转换流
字符编码:就是一套自然语言的字符与二进制之间的对应规则
字符集:也就是编码表 是一个系统支持的所有字符的集合 包括各国家文字,标点符号 图形符号 数字等 常见的编码表:Ascii字符集 ISO-8859-1字符表 GBXxx字符集 Unicode字符集等
常见的编码问题:
使用 FileReader 读取项目中的文本文件。由于IDEA的设置,都是默认的 UTF-8 编码,所以没有任何 问题。但是,当读取Windows系统中创建的文本文件时,由于Windows系统的默认是GBK编码,就会出现乱码。 怎么去解决呢?
转换流IO.InputStreamReader 是Reader的子类 是从字节流到字符流的桥梁 它读取字节 并使用指定的字符集将其解码为字符 它的字符集可以由名称指定 也可以接收平台的默认字符集
构造方法:
InputStreamReader(InputStream in):创建一个使用默认字符集的字符流
InoutStreamReader(InputStream in,String charsetName):创建一个指定字符集的字符流
代码示例:
InputStramReader(InputStream in):创建一个使用默认字符集的字符流
InputStramReader(InputStream in,String charsetName):创建一个指定字符集的字节流
OutputStreamWriter类
转换流IO.OutputStreamWriter 是Writer的子类 是从字符流到字节流的桥梁.使用指定的字符集将字符编码为字节 它的字符集可以由名称指定 也可以接收平台的默认字符集
构造方法:
OutputStreamWriter(OutputStream in):创建一个使用默认字符集的字符流
OutputStreamWriter(OutputStream in,String charsetName):创建一个指定字符集的字符流
代码示例:
OutputStreamWriter isr=new OutputStreamWriter(new FileOutputStream("out.txt"));
OutputStreamWriter isr2=new OutputStreamWriter(new FileOutputStream("out.txt"),"GBK");
序列化
用一个字节序列可以表示一个对象 该字节序列包含该对象的数据 对象的类型和对象中存储的属性等信息。字节序列写出到文件之后 相当于文件中持久保存了一个对象的信息,都可以用来在内存中创建对象。反之 字节序列还可以从文件中读取出来 重构对象 对它进行反序列化。对象的数据 对象的类型和对象中存储的数据信息,都可以用来在内存中创建对象
ObjectOutputStream类:
IO.ObjectOutputStream类 将Java对象的原始数据类型写出到文件 实现对象的持久存储
构造方法:
public ObjectOutputStream(OutputStream out):创建一个指定OutputStream的ObjectOutputStream
代码示例:
FileOutputStream fileout=new FileOutputStream("employee.txt");
ObjectOutputStream out=new ObjectOutputStream(fileOut);
序列化操作:
1.对象想要序列化 必须满足两个条件:
该类必须实现IO.Serializable接口,Serializable是一个标记接口 不实现此接口的类将不会使任何状态序列化或反序列化 会抛出NotSerializableException
该类的所有属性必须使可序列化的 如果由一个属性不需要可序列化的 则该属性必须注明使瞬态的 使用transient关键字修饰
2.写出对象方法
public final void writeObject(object obj):将指定的对象写出
ObjectInputStream类:
ObjectInputStream反序列化流 将之前使用ObjectOutputStream序列化的原始数据回复为对象
构造方法:
public ObjectInputStream(InputStream in):创建一个指定InputStream的ObjectInputStream读取对象的方法:
如果能找到一个对象的class文件 我们可以进行反序列化操作 调用objectInputStream读取对象的方法:
public final object readObject():读取一个对象
对于JVM可以反序列化对象 它必须使能够找到class文件的类 如果找不到该类的class文件 则抛出一个classNotFoundException异常
另外 当JVM反序列化对象时 能找到class文件 但是class文件在序列化对象之后发生了修改该 那么反序列化 操作也会失败 抛出一个InvalidClassException异常 会导致这个异常的原因是:
1.该类的序列版本号从流中读取的类描述符的坂本号不匹配
2.该类包含未知数据类型
3.该类没有可访问的无参构造方法
Serializable接口 给需要序列化的类 提供了一个序列版本号 serialVersionUID该版本的目的在于沿着序列化的对象和对于类是否版本匹配
打印流
说到打印 我们就会想起学Java时学的第一句语句System.out.println()和System.out.print() 这两个方法都老子io.PrintStream类,该类能够方便地打印各种数据类型的值 是一种便捷的输出方式
PrintStream类:
构造方法:
public PrintStream(String fineName):使用指定的文件名创建一个新的打印流
代码示例:
PrintStream ps=new PrintStrem("aa.txt");
改变打印流向:
System.out 就是PrintStream类型的 只不过它的流向是系统规定的 打印在控制台是 我们也可以改变它的流向
//调用系统的打印流,控制台直接输出97 System.out.println(97); //创建打印流 指定文件名称 PrintStream ps=new PrintStream("aa.txt"); //设置系统的打印流流向 输出到文件 System.setOut(ps); //调用系统的打印流 aa.txt中输出97 System.out.println(97);