Loading

Java学习笔记 -IO流2

缓冲流 & 转换流

示例1 -BufferedReader

(1)知识点:

  • BufferedReader: 带有缓冲区的的字符输入流
    使用这个流的时候不需要自定义char数组或者byte数组,自带缓冲

  • 构造方法:BufferedReader(Reader in) 缓冲流的使用需要传递参数:字符流,字节流不行

  • 概念:包装流 & 节点流

  • 方法:readLine() 读取一行,会丢弃换行符,如果读取到文件结尾则返回null

(2)程序:

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

public class BufferedReaderTest01 {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            //当一个流的构造方法需要一个流的时候:这个流称为节点流
            //外部负责包装的流:包装流 或 处理流
            FileReader reader = new FileReader("111.txt");

            //参数必须是字符流不能是字节流
            br = new BufferedReader(reader);

            String s = null;
            while ((s = br.readLine()) != null){
                System.out.println(s);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

示例2 -转换流的使用

(1)知识点:

  • 转换流:将字节流转换为字符流
  • 构造方法:InputStreamReader(InputStream in)

(2)程序(没有处理异常):

public class BufferedReaderTest02 {
    public static void main(String[] args) throws IOException {
        //字节流
        FileInputStream fis = new FileInputStream("111.txt");
        //转换流:字节 -》 字符
        InputStreamReader isr = new InputStreamReader(fis);
        //缓冲流
        BufferedReader br = new BufferedReader(isr);

        String str = null;
        while((str = br.readLine()) != null){
            System.out.println(str);
        }

            br.close();
    }
}

示例3 -BufferedWriter

  • 构造方法:BufferedWriter(Writer out)

程序(没有处理异常):

public class BufferedWriteTest01 {
    public static void main(String[] args) throws IOException {

        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("111.txt",true)));
        bw.write("Hellowordl\n");
        bw.write("ddddrrrrr");

        bw.flush();

        bw.close();
    }
}

数据流

  • 数据流可以将数据连同数据类型一同写入文件,该文件不是普通的文本类型

  • DataOutStream写的文件,只能使用DataInputStream去读,
    并且读取的顺序要和写入的顺序相同,才可以正常读出数据

  • 构造方法:DataOutputStream(OutputStream out)
    DataInputStream(InputStream in)

程序(没有处理异常):

public class DataOutputStreamTest01 {
    public static void main(String[] args) throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data"));

        byte b = 100;
        short s = 200;
        int i = 200;
        char c = 'a';

        //写入
        dos.writeByte(b);
        dos.writeShort(s);
        dos.writeInt(i);
        dos.writeChar(c);

        dos.flush();
        dos.close();

        //=====================================================
        DataInputStream dis = new DataInputStream(new FileInputStream("data"));

        System.out.println(dis.readByte());
        System.out.println(dis.readShort());
        System.out.println(dis.readInt());
        System.out.println(dis.readShort());

        dis.close();
    }
}

标准输出流

  • java.io.PrintStream:标准的字节输出流,默认输出到控制台
  • 标准输出流不需要手动关闭
  • 标准输出流比较重要的就是:修改标准输出流的输出方向

程序:

public class PrintStreamTest {
    public static void main(String[] args) throws FileNotFoundException {

        //等价于 System.out.println("Hello World");
        PrintStream ps = System.out;
        ps.println("Hello World");

        //标准输出流可以指定输出方向,指向"log"文件
        PrintStream printStream = new PrintStream("log");
        //修改输出方向,将输出方向修改到"log"文件
        System.setOut(printStream);

        System.out.println("hello kitty");
    }
}

对象专属流

对象专属流的作用:

知识点:

  • 参与序列化和反序列化的对象,必须实现Serializable接口
    如果没有实现就将其序列化,会报异常:java.io.NotSerializableException

  • Serializable接口只是一个标志性接口,什么代码都没有,只是起到标识的作用,给JVM看的
    JVM看到Serializable接口之后,会为该类自动生成一个序列化版本号

  • 序列化版本号
    (1)java靠什么机制区分类?

    • 包名+类名
    • 如果类名一样,则靠序列化版本号

    (2)默认自动生成序列化版本号,但是这种方式有缺点:

    • 一旦代码确定之后,不能进行后续的修改,
    • 因为修改,则必然重新编译,此时生成全新的序列化版本号,这个时候JVM会认为这是一个全新的类
  • 最终结论: 凡是一个类实现了Serializable接口,建议给该类手动分配一个序列化版本号
    private static final long serialVersionUID = 1l;

  • transient关键字表示游离的,修饰的属性不参与序列化

  • 如果存放多个对象,要使用集合的方式,如果一个一个序列化,则第二个会报错

示例程序:

import java.io.Serializable;

public class Student implements Serializable {
    //手动分配
    private static final long serialVersionUID = 1l;

    //transient关键字表示游离的,修饰的属性不参与序列化
    private transient String name;
    private int age;

    public Student() {}
    public Student(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 "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class ObjectOutputStreamTest01 {
    public static void main(String[] args) throws IOException {
        //创建java对象
        Student s = new Student("zhaosan",13);
        Student s1 = new Student("ls",34);

        List<Student> list = new ArrayList<>();
        list.add(s);
        list.add(s1);

        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("studentClass"));

        //序列化对象
        oos.writeObject(list);

        oos.flush();

        oos.close();
    }
}
public class ObjectInputStreamTest01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("studentClass"));

        //反序列化,读取类
        List<Student> list = (List<Student>) ois.readObject();
        for(Student s : list) {
            System.out.println(s);
        }
        ois.close();
    }
}
posted @ 2020-05-31 21:12  Krocz  阅读(148)  评论(0编辑  收藏  举报