缓冲流、转换流、序列化流

缓冲流、转换流、序列化流

第一章 缓冲流

昨天学习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流。比如能够高效读写的缓冲流,能够 转换编码的转换流,能够持久化存储对象的序列化流等等。这些功能更为强大的流,都是在基本的流对象基础之上 创建而来的,就像穿上铠甲的武士一样,相当于是对基本流对象的一种增强。

缓冲字节输入流

BufferedInputStream

package com.hqyj.demo07;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
java.io.InputStream
    java.io.FilterInputStream
        java.io.BufferedInputStream
java.io.InputStream
此类是一个抽象类,表示输入字节流的所有类的超类
定义一些子类共性的成员方法:
public abstract int read()throws IOException从输入流读取数据的下一个字节。
public int read(byte[] b)throws IOException从输入流读取一些字节数,并将它们存储到缓冲区b 。
public int read(byte[] b,int off,int len)throws IOException从输入流读取len字节的数据到一个字节数组。

java.io.BufferedInputStream
构造方法:
public BufferedInputStream(InputStream in)
创建一个BufferedInputStream并保存其参数,输入流in供以后使用。
public BufferedInputStream(InputStream in,int size)
创建具有BufferedInputStream缓冲区大小的BufferedInputStream,并保存其参数,输入流in供以后使用。
 */
public class BufferedInputStreamTest01 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        /*int len = 0;//字节
        while ((len=bis.read())!=-1){
            System.out.println(len);
        }*/


        byte[] bytes = new byte[1024];//字节
        int len = 0;//有效字节数
        while ((len=bis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        fis.close();
        bis.close();
    }
}

缓冲字节输出流

BufferedOutputStream

package com.hqyj.demo07;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
java.io.OutputStream
    java.io.FilterOutputStream
        java.io.BufferedOutputStream
此类是一个抽象类,表示输出字节流的所有类的超类
定义一些子类共性的成员方法:
public void close()throws IOException关闭此输出流并释放与此流相关联的任何系统资源
public void flush()throws IOException刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b)throws IOException将b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b,int off,int len)throws IOException从指定的字节数组写入len字节,从偏移off开始输出到此输出流。
public abstract void write(int b)throws IOException将指定的字节写入此输出流。

java.io.BufferedOutputStream
构造方法:
public BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
public BufferedOutputStream(OutputStream out,int size)
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。
 */
public class BufferedOutputStreamTest01 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("a.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        bos.write("我把数据写在内部缓冲区".getBytes());
        bos.flush();
        bos.close();
    }
}

缓冲字符输入流

BufferedReader

特有的方法:
public String readLine() throws IOException读一行文字。

package com.hqyj.demo07;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/*
java.io.Reader
    java.io.BufferedReader
定义一些子类共性的成员方法:
public int read()throws IOException
spublic int read(char[] cbuf)throws IOException将字符读入数组。

java.io.BufferedReader
构造方法:
public BufferedReader(Reader in)创建使用默认大小的输入缓冲区的缓冲字符输入流。
public BufferedReader(Reader in,int sz)创建使用指定大小的输入缓冲区的缓冲字符输入流。
特有的方法:
public String readLine()throws IOException读一行文字。
 */
public class BufferedReaderTest01 {
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new FileReader("b.txt"));
        String line;
        while ((line=br.readLine())!=null){
            System.out.println(line);
        }
        br.close();
    }
}

字符缓冲输出流

BufferedWriter

特有的方法:
public void newLine() throws IOException写一行,行分隔符

package com.hqyj.wy.Demo1;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/*
java.io.Writer
    java.io.BufferedWriter
定义一些子类共性的成员方法:
public void write(int c) throws IOException写一个字符
public void write(char[] cbuf) throws IOException写入一个字符数组。
public abstract void write(char[] cbuf,int off,int len) throws IOException写入字符数组的一部分。
public void write(String str)throws IOException写一个字符串
public void write(String str,int off,int len)throws IOException写一个字符串的一部分。
public abstract void flush()throws IOException刷新流。
public abstract void close()throws IOException关闭流,先刷新

java.io.BufferedWriter
构造方法:
public BufferedWriter(Writer out)创建使用默认大小的输出缓冲区的缓冲字符输出流。
public BufferedWriter(Writer out,int sz)创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
特有的方法:
public void newLine()throws IOException写一行,行分隔符。
 */
public class BufferedWriterTest01 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
        for (int i = 0; i < 10; i++) {
            bw.write("你好,JAVA");
            bw.newLine();//换行  ==  \r \n
        }
        bw.close();
    }
}

缓冲字节输入输出流效率高

package com.hqyj.demo07;

/*
缓冲字节输入输出流效率高:
图片文件复制:一边读一边写
数据源:d:\\2.jpg
数据的目的地:e:\\2.jpg
文件复制的步骤:
1.创建一个缓冲字节输入流对象,构造方法中要绑定要读取的数据源
2.创建一个缓冲字节输出流对象,构造方法中要绑定要写入的数据的目的地
3.使用read()和write()方法,一边读一边写
4.释放资源

复制文件共消耗:3毫秒
 */
import java.io.*;
public class FileCopy02 {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\1.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\1.jpg"));
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len=bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }
        bis.close();
        bos.close();
        long end = System.currentTimeMillis();
        System.out.println("共耗时:"+(end-start)+"毫秒");
    }
}

2.2编码引出的问题

转换流

package com.hqyj.demo08;

import java.io.FileReader;
import java.io.IOException;

/*
FileReader可以读取IDEA默认编码格式(UTF-8)
FileReader可以读取系统默认编码(中文GBK)格式会产生乱码����
 */
public class FileReaderTest {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("我是GBK文件.txt");
        int len = 0;
        while ((len=fr.read())!=-1){
            System.out.println((char)len);
        }
        fr.close();
    }

package com.hqyj.demo08;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/*
java.io.Reader
java.io.InputStreamReader

public InputStreamReader(InputStream in,String charsetName)throws UnsupportedEncodingException
创建一个使用命名字符集的InputStreamReader。
 */
public class InputStreamReaderTest {
    public static void main(String[] args) throws IOException {
        read_utf_8();
    }
    //读取utf-8编码的文件
    private static void read_utf_8() throws IOException {
        InputStreamReader isr = new InputStreamReader(newFileInputStream("utf_8.txt"),"utf-8");
        int len = 0;
        while ((len=isr.read())!=-1){
            System.out.println((char)len);
        }
            isr.close();
    }
}
package com.hqyj.demo08;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/*
java.io.Writer
java.io.OutputStreamWriter

public OutputStreamWriter(OutputStream out,
                          String charsetName)
                   throws UnsupportedEncodingException创建一个使用命名字符集的OutputStreamWriter。
 设置编码的时候,参数不区分大小写 GBK/gbk;UTF-8/utf-8
 不指定编码默认用UTF-8
 */
public class OutputStreamWriterTest {
    public static void main(String[] args) throws IOException {
        write_gbk();
    }
    //写入GBK编码文件
    private static void write_gbk() throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
        osw.write("你好鸭");
        osw.flush();
        osw.close();
    }
}

序列化

ObjectOutputStream类

package com.hqyj.demo09;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/*
序列化:将对象写入到文件中
java.io.OutputStream
    java.io.ObjectOutputStream
构造方法:
public ObjectOutputStream(OutputStream out)
                   throws IOException
特定方法:
public final void writeObject(Object obj)
                       throws IOException
 */
public class ObjectOutputStreamTest {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));
        oos.writeObject(new Person("易烊千玺",21));
        oos.close();
    }
}

反序列化:将对象从文件中读取出来

package com.hqyj.demo09;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/*
反序列化:将对象从文件中读取出来
java.io.InputStream
java.io.ObjectInputStream

构造方法:
public ObjectInputStream(InputStream in)
                  throws IOException创建从指定的InputStream读取的ObjectInputStream。
特定方法:
public final Object readObject()
                        throws IOException,
                               ClassNotFoundException

异常:没序列化异常
Exception in thread "main" java.io.NotSerializableException: com.hqyj.demo09.Person
前提:
Person类要实现Serializable接口(序列化接口-标记型接口),启动序列化功能,不实现会报以上异常
 */
public class ObjectInputStreamTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"));
        Object o = ois.readObject();
        Person p =(Person)o;
        System.out.println(p.getName()+"-"+p.getAge());
        ois.close();
    }
}
package com.hqyj.demo09;

import java.io.Serializable;

/**
 * 不添加序列化版本号,会报以下异常:
 * 表明Person类在改动前后生成了两个序列化版本号,不一致导致无法反序列化
 *  java.io.InvalidClassException:
 *  com.hqyj.demo09.Person; local class incompatible:
 *  stream classdesc serialVersionUID = 842344862260111050,
 *  local class serialVersionUID = -4421721788509217275
 *
 * 不被序列化的两个关键字:
 *transient static
 */
public class Person implements Serializable {
    private static final long serialVersionUID = -2782143034241084058L;
    //序列化版本号
    //private static final long serialVersionUID = 12L;
    private String name;
    private int age;
    //private transient int age;//不被序列化
    //private static int age;//不被序列化
    private String hobby;
    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

打印流

package com.hqyj.demo10;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/*
java.io.OutputStream
    java.io.FilterOutputStream
        java.io.PrintStream
特点:
1.只负责数据的输出,不负责数据的读取
2.与其他流不同,它不会抛出IOException
3.特有的方法:print(),println()

注意:
使用继承自父类中的write方法,那么它查看数据的时候会自动查看编码表,97-a
使用自己特有的print(),println()方法,它写入的数据会原样写入,97-97
 */
public class PrintStreamTest01 {

    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("print.txt");
        ps.write(97);
        ps.println(97);
        ps.println(true);
        ps.print("abc");
        ps.close();
    }
}
package com.hqyj.demo10;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/*
改变输出流的目的地(打印流的语句)
输出语句默认打印到控制台
使用System.setOut可以改变输出语句的目的地,改为参数中传递的打印流的目的地
public static void setOut(PrintStream out)重新分配“标准”输出流。
 */
public class PrintStreamTest02 {
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("我是打印到控制台的");//打印到控制台
        PrintStream ps = new PrintStream("end.txt");
        System.setOut(ps);
        System.out.println("我是打印到end.txt的");//打印到end.txt
        ps.close();
    }
}
上一篇:javaSE 笔记 异常 + try...catch... + throws/throw + 自定义异常


下一篇:异常处理的两种方式