java基础-关于io流-学习笔记

流的概念:

流是有起点和终点的有序字节序列

流的分类:

输入流/输出流:是当前程序为参照点,程序从外面读数据 就是输入流,把程序里面的数据保存到外面就是输出
字节流/字符流:以字节为单位处理流中的数据就是字节流,以字符为单位处理流中的数据就是字符流
节点流/处理流:如果直接从设备上(数据源)读写数据就是节点流,处理流就是节点流的包装

在程序中从文件读写数据用IO流,java定义了相关的流类在 java.io包中,如果这个类是以Stream单词结尾就是字节流,如果这个类以Reader结尾就是字符输入流,以Writer结尾就是字符输出流

一、FileReader、FileWriter

FileReader与FileWriter只能读写与当前环境编码兼容的文本文件,如果文件与当前编码不兼容,使用InputStreamReader、OutputStreamWriter

private static void m1() throws IOException {
        Reader in =new FileReader("/Users/xxx/Downloads/测试文件/xxx.text");
        BufferedReader br=new BufferedReader(in);
        //从缓冲字符流中读取一行
        String line=br.readLine();
        while (line!=null){
            System.out.println(line);
            line=br.readLine();
        }
        br.close(); //把包装流关闭后,被包装的流也会关闭
    }
    private static void m2() throws IOException{
        Writer out=new FileWriter("/Users/xxx/Downloads/测试文件/abc.txt",true);
        BufferedWriter bw=new BufferedWriter(out);
        bw.write("裂开了");
        bw.flush();
    }

二、FileInputStream / FileOutPutStream 转换流(把字节转换为字符,把字符转换为字节)

转换流读写 转化流采用了适配器设计模式

private static void m1() throws IOException {
    //在当前程序与指定文件中建立字节流通道,该文件使用GBK编码,当前环境使用UTF-8编码 把字节转化为字符;在当前程序与指定文件建立流通道
    InputStream in=new FileInputStream("/Users/xxx/Downloads/未命名文件夹/xxx.text");
    //使用GBK编码把in 中的字节流 转化为字符流
    InputStreamReader isr=new InputStreamReader(in,"GBK");
    int cc=isr.read();
    while (cc!=-1){
        System.out.println((char)cc);
        cc=isr.read();
    }
    isr.close();
}
public static void main(String[] args) throws IOException {
    m1(); //使用InputStreamReader读取文件
    m2(); //使用OutputStreamWriter保存数据
}
//当操作的文件编码与当前编码不兼容,使用OutputStreamWriter把指定的字符转化为字节
private static void m2() throws IOException{
    //把字符保存在d盘  该文件是GBK编码,当前环境是UTF-8编码,把字符转化为GBK的字节
   OutputStream out=new FileOutputStream("/Users/xxx/Downloads/未命名文件夹/xxx.text",true);
    OutputStreamWriter osw=new OutputStreamWriter(out,"GBK");
    osw.write("xdsdddddd");
    osw.write("当前的内容是使用转换流保存到文件中的,工作区编码是utf8,该文件使用gmb编码 需要(使用转化流)");
    osw.close();
    }

三、字符缓冲流(处理流 包装流):BufferedReader/BufferedWriter

默认有8192字符大小的缓冲区,实际上是一个8192字符大小的数组

1)程序不直接从文件中读取数据,使用FileReader从文件中读取数据,读到BufferedReader的缓冲区中,程序是从缓冲区读取数据
2)程序是把文件保存在BufferedWriter缓冲区中,在使用FileWriter把缓冲区的数据保存在文件内,注意BufferedWriter缓冲区的数据并不是立即保存到文件中,而是符合以下条件时再保存到文件中:
缓冲区满; 调用了flush() ;调用了close()方法

public class BufferDemo {
    private static void m1() throws IOException {
        Reader in =new FileReader("/Users/xxx/Downloads/测试文件/xxx.text");
        BufferedReader br=new BufferedReader(in);
        //从缓冲字符流中读取一行
        String line=br.readLine();
        while (line!=null){
            System.out.println(line);
            line=br.readLine();
        }
        br.close(); //把包装流关闭后,被包装的流也会关闭
    }
    private static void m2() throws IOException{
        Writer out=new FileWriter("/Users/xxx/Downloads/测试文件/abc.txt",true);
        BufferedWriter bw=new BufferedWriter(out);
        bw.write("裂开了");
        bw.flush(); //清空缓冲区,把数据保存到文件中
    }
    private static void m3() throws IOException{
        BufferedWriter bw=new BufferedWriter(new FileWriter("/Users/xxx/Downloads/测试文件/xyz.txt"));
        //使用BufferedReader对键盘输入缓冲流  System.in 是一个字节流,InputStreamReader(System.in) 把字节流转化为字符流进行缓冲
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String line=br.readLine();
        while (line.length()>0){
            bw.write(line);
            bw.newLine();
            line=br.readLine();
        }
        br.close();
        bw.close();

    }
    public static void main(String[] args) throws IOException {
        m1(); //使用BufferedReader读取文件
        m2(); //使用BufferedWriter保存文本到文件
        m3(); //从键盘输入文本 把文本保存到文件中
    }
}

四、ObjectInputStream/ObjectOutputStream

对象序列化:将对象转化为01二进制序列就是对象的序列化
对象反序列化:将01二进制序列转为为对象 叫做对象的反序列化

对象序列化与对象反序列化 前提是对象要实现Serializable接口,该接口是一个标志性接口,没有任何方法

ObjectOutputStream类 可以把对象序列化,并把序列化后的二进制保存到文件中

ObjectInputStream类 可以从文件中读取01序列,把这组01序列转化为对象

一般情况下 类实现了Serializable接口后,会手动添加一个序列化版本号字段

public class Person implements Serializable {
    String name;
    int age;
    // 场景描述:对象序列化文件后,又在Person类中添加了一个字段,在进行反序列化时 产生以下异常 
   //解决办法:手动添加一个序列化版本号字段
    private static final long serialVersionUID=-378787384333L;
    String genter;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

//对象序列化,把对象存在文件内

class Test{
    public static void main(String[] args) throws IOException {
        Person p1=new Person("勇哥",36);
        //对象序列化,把person对象保存到文件中
        OutputStream out=new FileOutputStream("/Users/xxx/Downloads/测试文件/obj.txt");
        ObjectOutputStream oos=new ObjectOutputStream(out);
        oos.writeObject(p1);
        oos.close();
    }
}

//对象反序列化

class Test01{
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        InputStream in=new FileInputStream("/Users/xxx/Downloads/测试文件/obj.txt");
        ObjectInputStream ois= new ObjectInputStream(in);
        //从文件中读取一个对象
        Object obj=ois.readObject();
        System.out.println(obj);
        ois.close();
        /*
        java.io.InvalidClassException
        场景描述:对象序列化文件后,又在Person类中添加了一个字段,在进行反序列化时 产生以下异常
        local class incompatible: stream classdesc serialVersionUID = 6636703827534086553, local class serialVersionUID = 2176066548359559320
   at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)

         */
    }
}

五、PrintStream:打印字节流

打印异常信息PrintStream 字节为单位

public static void main(String[] args)throws IOException {
    //1)建立了流通道,创建字节流
    OutputStream out=new FileOutputStream("/Users/xxx/Downloads/测试文件/log.txt",true);
    //创建打印流
    PrintStream pStream=new PrintStream(out);
    pStream.print("hello");
    pStream.println(" hello");
    //System 的out成员  就是PrintStream的打印流;System.out的默认输出设备是显示器
    System.out.println("默认在显示器上打印信息");
    //可以修改System.out的打印方向
    System.setOut(pStream);
    System.out.println("这一行信息是打印到pStream流中,即log.txt文件中");
    //经常把日志信息保存到文件中
    try{
        FileInputStream fis=new FileInputStream("/xxxxx");//建立流通道
    }catch (Exception e){
        //在开发时 一般调用e.printStackTrace把异常信息打印在屏幕上方便调试
        //在部署后 把异常信息打印到日志文件中
        e.printStackTrace(pStream);
    }
    pStream.close();
}

PrintWriter字符打印流 字符为单位

posted @ 2021-08-07 22:40  只要不兔的学习笔记  阅读(109)  评论(1)    收藏  举报