IO流(缓冲流、转换流、序列化流)

继续学习IO流:

分类:

  • 字节流
    • OutputStream
      • FileOutputStream
        • BufferedOutputStream
      • ObjectOutputStream
    • InputStream
      • FileInputStream
        • BufferedInputStream
      • ObjectInputStream
  • 字符流
    • Writer
      • OutputStreamWriter
        • FileWriter
      • BufferedWriter
    • Reader
      • InputStreamReader
        • FileReader
      • BufferedReader

上篇学习完了一些基本的输入输出流,本篇学习一些更强大的流——高效读写的缓冲流、转换编码的转换流、持久化存储对象的序列化流

  • 缓冲流(BufferedOutputStream、BufferedInputStream、BufferedWriter、BufferedReader)
  • 转换流(OutputStreamWriter、InputStreamReader)
  • 序列化流(ObjectOutputStream、ObjectInputStream)

缓冲流

也叫高效流,创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO的次数,从而提高读写的效率。

缓冲流中并没有增加什么新的方法,

缓冲流都是和基本流一起来使用,提高了读写效率。(构造方法中都要传入一个 基本流)

字节缓冲流
BufferedOutputStream

继承自FileOutputStream,它的构造方法中通常传的也是FileOutputStream对象

构造方法:

  • public BufferedOutputStream(OutputStream out)创建一个BufferedOutputStream,保存其参数,输出流供以后使用(默认缓冲区大小,8192)

  • public BufferedOutputStream(OutputStream out,int size)创建一个BufferedOutputStream,保存其参数,输出流供以后使用,并指定其缓冲区大小

BufferedInputStream

继承自FileInputStream,它的构造方法中通常传的也是FileInputStream对象

构造方法:

  • public BufferedInputStream(InputStream in)创建一个BufferedInputStream,保存其参数,输入流供以后使用
  • public BufferedInputStream(InputStream in,int size)创建一个BufferedInputStream,保存其参数,输入流供以后使用,并指定其缓冲区大小
效率测试:
import java.io.*;

/**
 * 字节流拷贝文件
 */
public class Test1 {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream("F:\\FileTest\\jre-8u202-windows-x64.exe");
        FileOutputStream fos = new FileOutputStream("F:\\FileTest\\jre.exe");
        byte[] b = new byte[1024];
        int i=fis.read(b);
        while (i!=-1){
            fos.write(b);
            i = fis.read(b);
        }
        fos.flush();
        fis.close();
        fos.close();
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime-startTime)+"毫秒");
        //660毫秒
    }
}
import java.io.*;

/**
 * 字节缓冲流拷贝文件
 */
public class Test2 {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\FileTest\\jre-8u202-windows-x64.exe"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\FileTest\\jre2.exe"));
        byte[] b = new byte[1024];
        int i  = bis.read(b);
        while (i!=-1){
            bos.write(b);
            i =bis.read(b);
        }
        bos.flush();
        bos.close();
        bis.close();
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime-startTime)+"毫秒");
        //130毫秒
    }
}

可以自己测试一下,拷贝越大的文件效果越明显

缓冲流增加了读写的效率,同样因为字符缓冲区的存在,占用的内存会比基本流多

字符缓冲流
BufferedWriter

继承自Writer,构造方法中通常传入一个它父类的实现类FileWriter的对象

构造方法:

  • public BufferedWriter(Writer out)创建一个字符缓冲流,输出流供以后使用(默认缓冲区大小,8192)
  • public BufferedWriter(Writer out,int size)创建一个字符缓冲流,输出流供以后使用,并指定其缓冲区大小

特有方法:

  • public void newline():写一行行分隔符(就是换行的作用)
import java.io.*;

public class Test3 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\FileTest\\bufferedWriter.txt"));
        bw.write("一个字符串");
        bw.newLine(); //换行
        bw.write("第二个字符串");
        bw.close();
    }
}
BufferedReader

继承自Reader,构造方法中通常传入一个它父类的实现类FileReader的对象

构造方法:

  • public BufferedReader(Reader in)创建一个字符缓冲流,输入流供以后使用(默认缓冲区大小,8192)
  • public BufferedReader(Reader in,int size)创建一个字符缓冲流,输入流供以后使用,并指定其缓冲区大小

特有方法:

  • public String readLine():读一行字符
import java.io.*;

public class Test4 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("F:\\FileTest\\bufferedWriter.txt"));
        String str = br.readLine(); //每次读取一行字符,返回一个字符串
        while (str!=null){
            System.out.println(str);
            str = br.readLine();
        }
        br.close();
    }
}

转换流

从字节流到字符流的桥梁。它使用指定的字符集将其编码和解码为字符,所使用的字符集可以自己指定。

OutputStreamWriter

继承自Writer,输出流的转换流,它的直接子类是FileWriter

构造方法:

  • public OutputStreamWriter(OutputStream out)使用默认的字符集创建一个转换流
  • public OutputStreamWriter(OutputStream out,Charset cs)使用指定的字符集创建一个转换流
import java.io.*;

public class Test5 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\FileTest\\a.txt"),"GBK");
        osw.write("123abc");
        osw.write("哈哈");
        osw.flush();
        osw.close();
    }
}
InputStreamReader

继承自Reader,输入流的转换流,它的直接子类是FileReader

构造方法:

  • public InputStreamReaderr(InputStream in)使用默认的字符集创建一个转换流
  • public InputStreamReader(InputStream in,Charset cs)使用指定的字符集创建一个转换流
import java.io.*;

public class Test6 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\FileTest\\a.txt"),"GB18030");
        int i = isr.read();
        //返回此流使用的编码格式
        System.out.println(isr.getEncoding());
        while (i!=-1){
            System.out.println((char) i);
            i = isr.read();
        }
        isr.close();
    }
}

序列化流(对象输入输出流)

Java中提供了一种对象序列化的机制,用一个字节序列可以表示一个对象,该字节序列包含对象的数据、对象的类型、对象中存储的属性等信息,字节序列写出文件后,相当于文件中持久存储了一个对象信息。

反之,该字节序列还可以从文件中读取出来,重构对象,这就叫做反序列化,对象的数据,对象的流星和对象中存储的数据信息,都可以用来在内存中创建对象。

序列化后的数据可以以二进制的形式在网络中传输或者保存到本地,通过反序列化可以在任何一个终端进行数据的还原。

序列化一个对象的条件:

  • 该类必须实现java.io.Serializable接口,Serializable是一个标记接口,凡是实现了这个接口的类的对象都可以被序列化
  • 该类中的所有属性必须是可序列化的,如果有一个属性不需要序列化,则该属性需要使用transient(瞬态)修饰。
  • 该类中还应该有一个序列化版本号,如果没有会自动生成,但是在反序列化时,会用到版本号,在没有版本号的情况下,就会发生异常,反序列化失败
//自定义一个Student类,实现Serializable接口
public class Student implements Serializable {
    //定义一个版本号(可以使用工具生成,也可以自己写,格式不能错)
    private static final long serialVersionUID = -4426508077041924239L;
    //成员属性···
    //成员方法···
}
ObjectOutputStream(序列化)

构造方法:

  • public ObjectOutputStream(OutputStream out) 创建一个写入指定out的对象输出流

常用方法:

返回值方法名说明
voidwriteObject(Object obj)写入一个obj对象到ObjectOutputStream
voidflush()刷新流
voidclose()关闭流

ObjectOutputStream中不止能写入对象,还有很多写入基本数据类型的方法:writerByte、writerShort、writerInt、writerLong、writerFloat、writerDouble、writerBoolean、writerChar。还有:writerBytes写入一个字符串作为一个字节序列、writerChars写入一个字符串作为字符序列

import java.io.*;

public class Test7 {
    public static void main(String[] args) {
        File file = new File("F:\\student.txt");
        try (
                OutputStream os = new FileOutputStream(file,true);
                ObjectOutputStream oos = new ObjectOutputStream(os);
                ){
            Student s1 = new Student(1001,"张三",20);
            Student s2 = new Student(1002,"李四",20);
            Student s3 = new Student(1003,"王五",20);
            oos.writeObject(s1);
            oos.writeObject(s2);
            oos.writeObject(s3);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

写出的数据是二进制的形式,保存的文件类型可以随意,使用txt打开我们也看不懂,只有反序列化流才能读懂它。

ObjectInputStream(反序列化)

构造方法:

  • public ObjectInputStream(InputStream in) 创建一个读取指定in的对象输入流

常用方法:

返回值方法名说明
intavailable()返回可读取而不阻塞的字节数
ObjectreadObject()从ObjectInputStream中读取一个Object对象
voidclose()关闭流

相应的ObjectOutputStream中不止能读取一个对象,还有很多读取基本数据类型的方法:readerByte、readerShort、readerInt、readerLong、readerFloat、readerDouble、readerBoolean、readerChar。

反序列化时要注意,此时反序列化的对象要和序列化时相同,而且版本号也要相同

import java.io.*;

public class Test8 {
    public static void main(String[] args) {
        File file = new File("F:\\student.txt");
        try (
                InputStream is = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(is);
        ){
            while (is.available()>0){
                Student student = (Student) ois.readObject();
                System.out.println(student);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值