IO流(详解)+每种流(用法详解)+Lamda表达式(详解)+序列化,反序列化(理论)

 1.IO流大全图解

/*应该把自己当做参考物:inputStream输入流(向自己输入数据,调用给自己看)*/
/*还是把自己当做参考物:outputStream输出流(由自己向数据库中写出数据)*/

2.IO流分类

第一种:输入流和输出流 按照流的流向来分,可以分为输入流和输出流。输入,输出都是从程序运行所在内存的角度来划分的。 输入流:只能从中读取数据,而不能向其写入数据,由InputStream和Reader作为基类。 输出流:只能向其写入数据,而不能从中读取数据。由OutputStream和Writer作为基类

第二种:字节流和字符流 字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操作的数据单元不同。 字节流操作的数据单元是8位字节,由InputStream和OutputStream作为基类。 字符流操作的数据单元是16为的字符,由Reader和Writer作为基类

第三种:节点流和处理流 按照流的角色来分,可以分为节点流和处理流。

节点流:可以从向一个特定的IO设备(如磁盘、网络)读/写数据的流。也被称为低级流。节点流的另一端是明确的,是实际读写数据的流,读写一定是建立在节点流基础上进行的. 。

处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。也称为高级流。处理流不能独立存在,必须连接在其他流上,目的是当数据流经当前流时对数据进行加工处理来简化我们对数据的该操作.。

3.IO流操作代码的缩写(对比)+lamda表达式缩写

package demo;
import java.io.*;
import java.nio.charset.StandardCharsets;


public class Demo3 {
    public static void main(String[] args) {
        
/**各种流操作的融合与缩写*/
        try {//捕获异常              //四种操作融缩为一句大代码
            FileOutputStream fos = new FileOutputStream("fos.txt"); 
            OutputStreamWriter osw = new OutputStreamWriter(fos,StandardCharsets.UTF_8);
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw =new PrintWriter(bw,true);
            
            pw.println("摩擦摩擦");
            pw.println("我爱学习Java");
            System.out.println("输出完毕");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
---------------------------------------------------------------------------------
        try {//
            PrintWriter pw =new PrintWriter(
                    new BufferedWriter(
                            new OutputStreamWriter(
                                    new FileOutputStream("fos.txt",true),
                                    StandardCharsets.UTF_8))
                    ,true);
             //层层嵌套
            pw.println("摩擦摩擦");
            pw.println("我爱学习Java");
            System.out.println("输出完毕");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        
---------------------------------------------------------------------------------
/**lamda表达式的缩写*/    
/*语法格式:

  FileFilter filter=(参数类型 参数列表)->{
                      方法体
                     }
*/

        //new一个过滤器,在其内部减一个
        FileFilter filter = new FileFilter() {
            public boolean accept(File file) {
                return file.getName().endsWith(".txt");
            }
        };        
        
        //利用格式转换
        FileFilter filter1 = (File file)->{
            return file.getName().endsWith(".txt");
        };

        //lambda表达式中参数的类型可以忽略不写
        FileFilter filter2 = (file)->{
            return file.getName().endsWith(".txt");
        };

    	/*lambda表达式方法体中若只有一句代码,则{}可以省略
      	如果这句话有return关键字,那么return也要一并省略*/
        FileFilter filter3= (file)->
            file.getName().endsWith(".txt");
        
        //lambda表达式若只有一个参数则小括号也可以省略
        FileFilter filter4= file->
                file.getName().endsWith(".txt");
        

       	//参数可以简写 file简写为f
        FileFilter filter5= (f)->
                f.isFile();        //调用一个方法.isFile() 作用判断是否为文件
        
     
        
/**做题*/        
       isFile():判断当前File表示的是否为一个文件。
       使用lambda表达式创建文件过滤器正确的是___:

       A.FileFilter filter = ()->filter.isFile();
       B.FileFilter filter = (File f)->return f.isFile();
       C.FileFilter filter = (FileFilter f)->f.isFile();
       D.FileFilter filter = (f)->f.isFile();
       E.FileFilter filter = f->f.isFile();

    }
}

4. IO流各类详解

4.1 对象流: 知识点+代码(序列化+反序列化)

(为什么需要Java序列化和反序列化,我们很自然地会想Java序列化的好处。好处一是: 实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里)。好处二是: 利用序列化实现远程通信,即在网络上传送对象的字节序列。)

总的来说可以归结为以下几点:

(1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;
(2)通过序列化以字节流的形式使对象在网络中进行传递和接收;
(3)通过序列化在进程间传递对象;

4.1.1 序列化 :java序列化是指把java对象转化为字节序列的过程

package io; /*序列化*/
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
 * 对象流
 * java.io.ObjectOutputStream和ObjectInputSteam
 * 对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化
 *
 * 对象序列化:将一个java对象按照其结构转换为一组字节的过程
 * 对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)
 */
public class OOSDemo {
    public static void main(String[] args) throws IOException {
        //将一个Person对象写入文件person.obj
        String name = "苍老师";
        int age = 18;
        String gender = "女";
        String[] otherInfo = {"是一名台词不多的演员","来自岛国","爱好写大字","广大男性同胞的启蒙老师"};
        Person p = new Person(name,age,gender,otherInfo);
        System.out.println(p);

        FileOutputStream fos = new FileOutputStream("person.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(p);
        System.out.println("写出完毕!");

        oos.close();
    }
}

4.1.2 反序列化 :把字节序列恢复为对象的过程称为对象的反序列化

package io; /*反序列化*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
 * 使用对象输入流完成对象的反序列化
 */
public class OISDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //从person.obj文件中将对象反序列化回来
        FileInputStream fis = new FileInputStream("person.obj");
        ObjectInputStream ois = new ObjectInputStream(fis);
        /*
            Object readObject()
            该方法会进行对象的反序列化,如果对象流通过其连接的流读取的字节分析并非
            是一个java对象时,会抛出异常:ClassNotFoundException
         */
        Person p = (Person)ois.readObject();
        System.out.println(p);
    }
}

4.2 序列化:知识点+代码

 需要进行序列化的类必须实现接口:java.io.Serializable 实现序列化接口后最好主动定义序列化版本号这个常量。 这样一来对象序列化时就不会根据类的结构生成一个版本号,而是使用该固定值。 那么反序列化时,只要还原的对象和当前类的版本号一致就可以进行还原。
    
transient关键字可以修饰属性,用于在进行对象序列化时忽略不必要的属性,达到对象瘦身的目的 



*实体类代码*/      
package io;
import java.io.Serializable;
import java.util.Arrays;

/**
 * 使用当前类实例测试对象流的读写操作
 */
public class Person implements Serializable { //实现序列化
    public static final long serialVersionUID = 1L;  //定义了序列化版本号
    private String name;//姓名
    private int age;//年龄
    private String gender;//性别


    //有参构造                           
    public Person(String name, int age, String gender, String[] otherInfo) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() { //get方法
        return name;
    }
    public void setName(String name) { //set方法
        this.name = name;
    }
}

4.3 字符流+转换流

  • 字符流

  • ​java将流按照读写单位划分为字节流与字符流.
  • ​java.io.InputStream和OutputStream是所有字节流的超类
  • ​而java.io.Reader和Writer则是所有字符流的超类,它们和字节流的超类是(平级关系).
  • ​Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
  • ​字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成.

  • 转换流

  • ​java.io.InputStreamReader和OutputStreamWriter
  • ​它们是字符流非常常用的一对实现类同时也是一对高级流,实际开发中我们不直接操作它们,但是它们在流连接中是非常重要的一环.
  • ​使用转换输出流向文件中写入文本数据

5. IO流理论总结

缓冲流

​缓冲流是一对高级流,在流链接中链接它的目的是加快读写效率。缓冲流内部默认缓冲区为8kb,缓冲流总是块读写数据来提高读写效率。

    
​java.io.BufferedOutputStream缓冲字节输出流,继承自java.io.OutputStream 
	/*常用构造器*/
    BufferedOutputStream(OutputStream out):创建一个默认8kb大小缓冲区的缓冲字节输出流,并连接到参数指定的字节输出流上。
	BufferedOutputStream(OutputStream out,int size):创建一个size指定大小(单位是字节)缓冲区的缓冲字节输出流,并连接到参数指定的字节输出流上。  
    
	/*常用方法*/    
	flush():强制将缓冲区中已经缓存的数据一次性写出缓冲流的写出方法功能与OutputStream上一致,需要知道的时write方法调用后并非实际写出,而是先将数据存入缓冲区(内部的字节数组中),当缓冲区满了时会自动写出一次。
    
--------------------------------------------------------------------    
​java.io.BufferedInputStream缓冲字节输入流,继承自java.io.InputStream   
	/*常用构造器*/
    BufferedInputStream(InputStream in):创建一个默认8kb大小缓冲区的缓冲字节输入流,并连接到参数指定的字节输入流上。
	BufferedInputStream(InputStream in,int size):创建一个size指定大小(单位是字节)缓冲区的缓冲字节输入流,并连接到参数指定的字节输入流上。
    
	/*常用方法*/ 
    缓冲流的读取方法功能与InputStream上一致,需要知道的时read方法调用后缓冲流会一次性读取缓冲区大小的字节数据并存入缓冲区,然后再根据我们调用read方法读取的字节数进行返回,直到缓冲区所有数据都已经通过read方法返回后会再次读取一组数据进缓冲区。即:块读取操作

对象流

​对象流是一对高级流,在流链接中的作用是完成对象的序列化与反序列化
	序列化:是对象输出流的工作,将一个对象按照其结构转换为一组字节的过程。
	反序列化:是对象输入流的工作,将一组字节还原为对象的过程。

​java.io.ObjectInputStream对象输入流,继承自java.io.InputStream
	/*常用构造器*/
    ObjectInputStream(InputStream in):创建一个对象输入流并连接到参数in这个输入流上。
    
	/*常用方法*/ 
    Object readObject():进行对象反序列化,将读取的字节转换为一个对象并以Object形式返回(多态)。
	如果读取的字节表示的不是一个java对象会抛出异常:java.io.ClassNotFoundException
        
--------------------------------------------------------------------       
​java.io.ObjectOutputStream对象输出流,继承自java.io.OutputStream 
	/*常用构造器*/
    ObjectOutputStream(OutputStream out):创建一个对象输出流并连接到参数out这个输出流上

	/*常用方法*/ 
    void writeObject(Object obj):进行对象的序列化,将一个java对象序列化成一组字节后再通过连接的输出流将这组字节写出。  
/*序列化和对象流连用*/(void writeObject(Object obj):进行对象的序列化,将一个java对象序列化成一组字节后再通过连接的输出流将这组字节写出)   

​如果序列化的对象没有实现可序列化接口:java.io.Serializable就会抛出异常:java.io.NotSerializableException
​序列化接口java.io.Serrializable
    
​(Serializable)接口没有任何抽象方法,但是只有实现了该接口的类的实例才能进行序列化与反序列化。
实现了序列化接口的类建议显示的定义常量:static final long serialVersionUID = 1L;
可以为属性添加关键字transient,被该关键字修饰的属性在序列化是会被忽略,达到对象序列化瘦身的目的   

字符流

​java将流按照读写单位划分为字节与字符流。字节流以字节为单位读写,字符流以字符为单位读写。
    
​转换流java.io.InputStreamReader和OutputStreamWriter 
    功能无需掌握,了解其核心意义:
    1:衔接其它字节与字符流
	2:将字符与字节进行转换
	相当于是现实中的"转换器"
        
​PrintWriter  :具有自动行刷新功能的缓冲字符输出流   
    构造器:
	PrintWriter(String filename)
	PrintWriter(File file)
    常用方法:    
    void println(String line):按行写出字符串    

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值