缓冲流,转换流

1.缓冲流

1.定义

缓冲流,也是高效流,是对四个基本的FileXxx流的增强. 所以也是四个流

  • 字节缓冲流:BufferedInputStream, BufferedOutputStream
  • 字符缓冲流:BufferedReader, BufferedWriter

缓冲流的基本原理,实在创建对象时,会创建一个内置默认大小的缓冲区数组,通过缓冲区读写,减少系统io次数

2.字节缓冲流

构造方法
  • public BufferedInputStream(InputStream in):创建一个新的缓冲流对象
  • public BufferedOutputStream(OutputStream out):创建一个新的缓冲流对象

构造举例

// 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
// 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));

使用缓冲流进行案例实现

public class BufferedDemo{
  public static void main(String[] args){
    // 记录开始时间
    long start = System.currentTimeMillis();
    // 创建流对象
    try(
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk.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)+"毫秒");
    }
  }
}

使用数组,加快速度

public class BufferedDemo{
  public static void main(String[] args){
    // 记录开始时间
    long start = System.currentTimeMillis();
    // 创建流对象
    try(
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("jdk.exe"));
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.exe"));
    ){
      //读写数据
      int len;
      byte[] bytes = new byte[8*1024];
      while((len=bis.read())!=-1){
        bos.write(bytes, 0, len);
      }catch(IOException e){
        e.printStackTrace();
      }
      // 记录结束的时间
      long end = System.currentTImeMillis();
      System.out.println("索要时间为"+(end-start)+"毫秒");
    }
  }
}

3.字符缓冲流

构造方法
  • public BufferedReader(Reader in):创建一个新的缓冲输入流
  • public BufferedWriter(Writer out):创建一个新的缓冲输出流

构造举例

// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
特有方法

字符缓冲流的基本方法和普通字符流调用方式一致

  • BufferedReader:public String readLine():读一行文字
  • BuffferedWriter:public void newLine():写一行行分隔符,有系统定义符号

readLine方法演示

public class BufferedReaderDemo{
  public static void main(String[] args) throws IOException{
    //创建流对象
    BufferedReader br = new BufferedReader(new FileReader("in.txt"));
    //定义字符串,保存读取的一行文字
    String line = null;
    //循环读取,读到最后返回null
    while((line=br.read())!=null){
      System.out.println(line);
      System.out.println("-----");
    }
    //释放资源
    br.close();
  }
}

newLine方法演示

public class BufferedWriterDemo{
  public static void main(String[] args) throws IOException{
    // 创建流对象
    BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
    //写出数据
    bw.write("黑马");
    bw.newLine();
    bw.write("程序");
    bw.newLine();
    //释放资源
    bw.close();
  }
}

2.转换流

1.IuputStreamReader

转换流java.io/InputStreamReader, 是Reader的子类, 他读去字节, 并使用指定的字符集将其解码为字符.

构造方法
  • InputStreamReader(InputStream in):创建一个使用默认字符集的字符流
  • InputStreamReader(InputStream in, String charsetName):创建一个指定字符集的字符流

构造举例

InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"), "GBK");
指定编码读取
public class ReaderDemo{
  public static void main(String[] args) throws IOException{
    // 定义文件位置, 文件为gbk编码
    String FileName = "E:\\file_txt";
    // 创建流对象指定为GBK
    InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName), "GBK");
    //定义变量, 保存字符
    int read;
    //循环读取
    while((read=isr.read())!=-1){
      System.out.println((char) read);
    }
    //关闭资源
    isr.close();
  }
}

2.OutputStreamWrite

Write的子类

构造方法

  • OutputStreamWriter(OutputStream in):创建一个使用默认字符集的字符流
  • OutputStreamWriter(OutputStream in, String chasetName):创建一个指定字符集的字符流

构造例子

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
指定编码写出
public class OutputDemo{
  public static void main(String[] args) throws IOException{
		//定义文件路径
    String FileName = "E:\\out.txt";
    //创建流对象
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName), "GBK");
    osw.write("你好");
    osw.close();
  }
}

3.序列化

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

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化。对象的数据 、对象的类型 和对象中 存储的数据信息,都可以用来在内存中创建对象。

1.ObjectOutputStream类

构造方法
  • public ObjectOutputStream(OutputStream out):穿件一个指定的OutputStream的ObjectOutputStream

构造例子

FileOutputStream FileOut = new FileOutputStream("a.txt");
ObjectOutputStream out = new ObjectOutputStream(FileOut);
序列化操作

1.一个对象要想序列化,必须满足两个条件

  • 该类是java.io.Serializable接口,Serializable是一个标记接口,不实现此接口不会使用任何状态序列化和反序列化, 会抛出NotSerializableException
  • 该类的所有属性必须是可序列化的,如果有一个属性不要可序列化的, 则改属性必须是注明是瞬态的,使用transient关键字修饰
public class Employle implements java.io.Serializable{
  public String name;
  public String address;
  public transient int age; //tanisent瞬态修饰成员, 不会被序列化
}

2.写出对象方法

  • public final void writeObject(Object obj):将制定的对象写出
public class Serializable{
  public static void main(String[] args){
    Employee e = new Employee();
    e.name = "张三";
    e.address = "北大";
    e.age = 20;
    try{
      //创建序列化流对象
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("a.txt"));
      //写出对象
      out.writeObject(e);
      //释放资源
      out.close();
      Fileout.close();
      System.out.println("Serializable 打他 is saved")
    }catch(IOException i){
      i.printStackTrace();
    }
  }
}

2.ObjectInputStream

构造方法
  • public ObjectInputStream(InputStream in):穿件一个指定InputStream的ObjectInputStream.
反序列化操作1

如果可以找到一个对象的class文件,我们可以进行反序列化操作

  • public final Object readObject():读取一个对象
public class DeserialixeDemo{
  public static void main(String[] args){
    Employee e = null;
    try{
      //创建反序列化流
      FileInputStream fileIn = new FileInputStream("a.txt");
      ObjectInputStream in = new ObjectInputStream(FileIn);
      //读取一个对象
      e = (Employee) in .readObject();
      //释放资源
      in.close();
      fileIn.close();
    }catch(IOException i){
      //捕获异常
      i.printStackTrace();
      return;
    }catch(ClassNotFoundException c){
      // 捕获找不到异常
      System.out.println("not found");
      c.printStrackTrace();
      return;
    }
    // 无异常,直接打印输出
    System.out.println(e.name);
    System.out.println(e.address);
    System.out.println(e.age);
  }
}
反序列化操作2

另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操

作也会失败,抛出一个 InvalidClassException 异常。发生这个异常的原因如下:

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配
  • 该类包含未知数据类型
  • 该类没有可访问的无参数构造方法

Serializable 接口给需要序列化的类,提供了一个序列版本号。 serialVersionUID 该版本号的目的在于验证序 列化的对象和对应类是否版本匹配

public class Employee implements java.io.Serializable{
  //加入序列版本号
  private static final long serialVersionUID = 1L;
  public String name;
  public String address;
  //添加新的属性,重新编译
  public int eid;
  public void adressCheck(){
    System.out.println("adress check"+name+"--"+adress);
  }
}

4.打印流

平时我们使用控制台打印,print和println来自于java.io.PrintStream

1.PrintStream类

构造方法
  • public PrintStream(String FileName):使用指定的文件名创建一个新的打印流

构造例子

PrintStream ps = new PrintStream("ps.txt");
改变打印流向

System.out就是PrintStream类型的

public class PrintDemo{
  public static void main(String[] args) throws IOException{
    //调用系统的打印流
    System.out.println(97);
    //创建打印流,指定文件的名称
    PrintStream ps = new PrintStream("ps.txt");
    // 设置系统的流向到ps.txt中
    System.setOut(ps);
    //调用打印的方法, ps.txt中输出97
    System.out.println(97);
  }
}

 

posted on 2019-08-16 13:30  liudemeng  阅读(221)  评论(0编辑  收藏  举报