IO流详解笔记

一,介绍IO流:

                IO流:是指在计算机程序中用于处理输入和输出的数据流。

                                                                                        注:进行读写文件,读写的对象可以是文件,可以是网页内容。

                I:----input  输入:从程序外到程序里。把文档信息读到程序。
               O:---output 输出:信息从程序里输送到程序外。
               流:(管道):输送方法,信息在程序和程序外进行的交流。

二,IO流分类:

                共6种:

                    根据流方向:  输入流      输出流。   
                    根据流承载信息的大小:  字节流:(1个字节8位)       字符流:两个字节(16位能处理汉字)
                    根据流的功能:节点流:一根管处理某种数据对应的流           处理流:管套管嵌套处理。
                                                        补:节点流和处理流区别:        
                                                                                            1字符流和字节流都是节点流(只有输入输出功能)        处理流(有其它功能)
                                                                                             2节点流直接连接数据源,处理流连接节点流对象。

三,Io流使用举例:

1字节输入流读取文本文件:

public static void main(String[] args) throw IOException{
     //获取信息源   
    File f=new File("E:\\test.txt");

    //创建IO流对象
    FileInputStream f2=new FileInputStream(f);
    //读取信息
    int i=f2.read();
    while(i!=-1){
    System.out.print((char)i);
    i=f2.read();
    }
    //关闭信息源
    f2.close;
}

2,字节输出输入流读取输出图片:

 public static void main(String[] args) throws IOException {
        //获得数据源
        File Inf=new File("E:小狮子.png");
        File outf=new File("E:teat\\小狮子.png");
        //获得输出流
        FileInputStream f1=new FileInputStream(Inf);
        FileOutputStream f2=new FileOutputStream(outf);//对应想要输出的地址
        //读写信息
        byte[] bys=new byte[50];//设置缓冲区,弥补read()一次只读一个字节的缺点
        int i=f1.read(bys);
        while (i!=-1){
            f2.write(bys);//输出流对应write。
            i=f1.read(bys);
        }
        //关闭资源;后开的先关
        f2.close();
        f1.close();
    }

3字符流输入:(读取汉字)

 public static void main(String[] args) throws IOException {
        //获得数据源
        File Inf=new File("E:test.txt");
       //获取管道对象:
        //读汉字
        FileReader f=new FileReader(Inf);
        char[] cs=new char[50];//缓冲区
        int i=f.read(cs);
        while (i!=-1){//下一位无内容时,条件不满足,停止循环

            System.out.println(cs);
            i=f.read(cs);//判断下一位是否有内容
        }
        //关闭
        f.close();
    }

4,字符流输出:

 public static void main(String[] args) throws IOException {
        //获得信息源
        File file=new File("E:test.txt");
        //获得字符输出流对象,输出管道
        FileWriter fw=new FileWriter(file,true);//没有条件会覆盖当前test内容,有ture条件会在末尾追加。默认是false会覆盖内容。
        //写入
        Scanner input =new Scanner(System.in);
        System.out.println("输入信息,输入exit退出");
        String str=input.next();
        while (!"exit".equals(str)){
            fw.write(str+"\n");
            System.out.println("输入信息,输入exit退出");
            str=input.next();
        }
        //关闭流对象
        fw.close();
    }

4,缓冲字节流(处理流):

               相较于使用缓冲区读取IO流信息,使用缓冲流更加快捷迅速。

 public static void main(String[] args) throws IOException {
        //1.有一个源图片
        File f1 = new File("d:\\LOL.jpg");
        //2.有一个目标图片:
        File f2 = new File("d:\\LOL2.jpg");
        //3.有一个输入的管道 接 到 源文件:
        FileInputStream fis = new FileInputStream(f1);
        //4.有一个输出的管道 接到  目标文件上:
        FileOutputStream fos = new FileOutputStream(f2);
        //5.功能加强,在FileInputStream外面套一个管:BufferedInputStream:
        BufferedInputStream bis = new BufferedInputStream(fis);
        //6.功能加强,在FileOutputStream外面套一个管:BufferedOutputStream:
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //7.开始动作 :
        byte[] b = new byte[1024*6];
        int len = bis.read(b);
        while(len!=-1){
            bos.write(b,0,len);
           /* bos.flush(); 底层已经帮我们做了刷新缓冲区的操作,不用我们手动完成:底层调用flushBuffer()*/
            len = bis.read(b);
        }
        //8.关闭流:
        //倒着关:
        //如果处理流包裹着节点流的话,那么其实只要关闭高级流(处理流),那么里面的字节流也会随之被关闭。
        bos.close();
        bis.close();
        /*fos.close();
        fis.close();*/
    }

5,缓冲字符流(处理流):

  public static void main(String[] args) throws IOException {
        //1.有一个源文件:
        File f1 = new File("d:\\Test.txt");
        //2.有一个目标文件:
        File f2 = new File("d:\\Demo.txt");
        //3.需要一个管 接到 源文件:
        FileReader fr = new FileReader(f1);
        //4.需要一根管接到目标文件:
        FileWriter fw = new FileWriter(f2);
        //5.套一根管在输入字符流外面:
        BufferedReader br = new BufferedReader(fr);
        //6.套一根管在输出字符流外面:
        BufferedWriter bw = new BufferedWriter(fw);
        //7.开始动作:
        //方式1:读取一个字符,输出一个字符:
        /*int n = br.read();
        while(n!=-1){
            bw.write(n);
            n = br.read();
        }*/
        //方式2:利用缓冲数组:
        /*char[] ch = new char[30];
        int len = br.read(ch);
        while(len!=-1){
            bw.write(ch,0,len);
            len = br.read(ch);
        }*/
        //方式3:读取String:
        String str = br.readLine();//每次读取文本文件中一行,返回字符串
        while(str!=null){
            bw.write(str);
            //在文本文件中应该再写出一个换行:
            bw.newLine();//新起一行
            str = br.readLine();
        }
        //8.关闭流
        bw.close();
        br.close();
    }

6,转换流(处理流):

                【1】转换流:作用:将字节流和字符流进行转换。
                【2】转换流  属于 字节流还是字符流?属于字符流
                        InputStreamReader  :字节输入流 --->字符的输入流
                        OutputStreamWriter  : 字符输出流 -->字节的输出流

    //将输入的字节流转换为字符流
 public static void main(String[] args) throws IOException {
        //文件---》程序:
        //1.有一个源文件:
        File f = new File("d:\\Test.txt");
        //2.需要一个输入的字节流接触文件:
        FileInputStream fis = new FileInputStream(f);
        //3.加入一个转换流,将字节流转换为字符流:(转换流属于一个处理流)
        //将字节转换为字符的时候,需要指定一个编码,这个编码跟文件本身的编码格式统一
        //如果编码格式不统一的话,那么在控制台上展示的效果就会出现乱码
        //InputStreamReader isr = new InputStreamReader(fis,"utf-8");
        //获取程序本身的编码--》utf-8
        InputStreamReader isr = new InputStreamReader(fis);
        //4.开始动作,将文件中内容显示在控制台:
        char[] ch = new char[20];
        int len = isr.read(ch);
        while(len!=-1){
            //将缓冲数组转为字符串在控制台上打印出来
            System.out.print(new String(ch,0,len));
            len = isr.read(ch);
        }
        //5.关闭流:
        isr.close();
    }
 public static void main(String[] args) throws IOException {
        //1.有一个源文件
        File f1 = new File("d:\\Test.txt");
        //2.有一个目标文件:
        File f2 = new File("d:\\Demo.txt");
        //3.输入方向:
        FileInputStream fis = new FileInputStream(f1);
        InputStreamReader isr = new InputStreamReader(fis,"utf-8");
        //4.输出方向:
        FileOutputStream fos = new FileOutputStream(f2);
        OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
        //5.开始动作:
        char[] ch = new char[20];
        int len = isr.read(ch);
        while(len!=-1){
            osw.write(ch,0,len);
            len = isr.read(ch);
        }
        //6.关闭流:
        osw.close();
        isr.close();
    }

7,数据流(处理流):

                        【1】数据流:用来操作基本数据类型和字符串的
                        【2】 DataInputStream:将文件中存储的基本数据类型和字符串  写入  内存的变量中
                                  DataOutputStream:  将内存中的基本数据类型和字符串的变量 写出  文件中

//利用DataOutputStream向外写出变量:

public class Test01 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) throws IOException {
        //DataOutputStream:  将内存中的基本数据类型和字符串的变量 写出  文件中
        /*File f = new File("d:\\Demo2.txt");
        FileOutputStream fos = new FileOutputStream(f);
        DataOutputStream dos = new DataOutputStream(fos);*/
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("d:\\Demo2.txt")));
        //向外将变量写到文件中去:
        dos.writeUTF("你好");
        dos.writeBoolean(false);
        dos.writeDouble(6.9);
        dos.writeInt(82);
        //关闭流:
        dos.close();
    }
}





//读取的程序:

public class Test02 {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) throws IOException {
        //DataInputStream:将文件中存储的基本数据类型和字符串  写入  内存的变量中
        DataInputStream dis = new DataInputStream(new FileInputStream(new File("d:\\Demo2.txt")));
        //将文件中内容读取到程序中来:
        System.out.println(dis.readUTF());
        System.out.println(dis.readBoolean());
        System.out.println(dis.readDouble());
        System.out.println(dis.readInt());
        //关闭流:
        dis.close();
    }
}

8,对象流(处理流);

                        【1】对象流:ObjectInputStream,ObjectOnputStream
                                用于存储和读取基本数据类型数据或对象的处理流。
                                它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。


                        【2】序列化和反序列化:
                                        ObjectOutputStream 类 : 把内存中的Java对象转换成平台无关的二进制数据,从而允许把这种二进制数据持久地保存在磁盘上,或通过网络将这种二进制数据传输到另一个网络节点。---->序列化
                                        ObjectInputStream类 : 当其它程序获取了这种二进制数据,就可以恢复成原来的Java对象。---->反序列化

//实验类
public class Student implements Comparable<Student>, Serializable {
    /**
     * 属性类型以包装类型存在!
     */
    private Integer stuId;
    private String stuName;
    private Integer age;
    private String sex;

    public Student() {
    }

    public Student(Integer stuId, String stuName, Integer age, String sex) {
        this.stuId = stuId;
        this.stuName = stuName;
        this.age = age;
        this.sex = sex;
    }

    public Integer getStuId() {
        return stuId;
    }

    public void setStuId(Integer stuId) {
        this.stuId = stuId;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) throws Exception {
        this.age = age;
        throw new Exception("提醒的内容");
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(stuId, student.stuId) &&
                Objects.equals(stuName, student.stuName) &&
                Objects.equals(age, student.age) &&
                Objects.equals(sex, student.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(stuId, stuName, age, sex);
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuId=" + stuId +
                ", stuName='" + stuName + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        /*if(stuId>o.stuId){
            return -1;
        }else if(stuId<o.stuId){
            return 1;
        }else{
            return 0;
        }*/
       return stuName.compareTo(o.stuName);
    }
}



//序列化


 public static void main(String[] args) throws IOException {
        //使用对象流”将内存对象----存储到外部文件:序列化:永久存储信息
        //将外部文件里信息,读取到内存:反序列化
        //获得信息源对象:
        File file=new File("E:test.txt");
        //获得管道对象
        //序列化,要有标记接口
        FileOutputStream fos=new FileOutputStream(file);//节点流
        ObjectOutputStream oos=new ObjectOutputStream(fos);//处理流
        //开始序列化
        Student stu=new Student(1,"xiao",24,"nan");
        oos.writeObject(stu);
        //关闭流对象,同一个方向,当有多层流对象时,关闭最里层。
        oos.close();
        System.out.println("序列化成功");

    }



//反序列化

public static void main(String[] args) throws IOException, ClassNotFoundException {
        //获得信息源对象:
        File file=new File("E:test.txt");
        //获得管道对象
        //序列化,要有标记接口
        FileInputStream fos=new FileInputStream(file);//节点流
        ObjectInputStream oos=new ObjectInputStream(fos);//处理流
        Student stu=(Student)oos.readObject();
        System.out.println(stu);
        oos.close();
        System.out.println("反序列化成功");
    }

          补:      

                        serialVersionUID:
                                                        凡是实现Serializable接口(标识接口)的类都有一个表示序列化版本标识符的静态常量:
                                ➢private static final long serialVersionUID;
                                ➢serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序加化时是否兼容。
                                ➢如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改,serialVersionUID 可能发生变化。故建议,显式声明。

                                ➢简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值