欢迎来到我的博客

将来的你一定会感激现在拼搏的自己

JavaSE基础day18 字符流、转换流、对象序列化


字符流

使用的原因

1、如果读取文件中的信息是纯英文,可以一次读取一个字节

2、如果文件中的信息是纯中文的,可以一次读取三个或者两个

3、如果文件中的信息是中英文混杂,每次读取几个,不确定容易出现乱码

小知识补充:

  在utf-8或者gbk的编码格式中,如果存储的是英文字符,该字符对应的字节肯定是正    数           

  如果存储的字符是中文字符,那么该在字符的第一个直接肯定是负数  

4、如果想要写出一个字符串信息到指定文件中,可以将字符串转为字节数6组,但是比较麻烦,而且浪费内存。  

 

概述

1、字符流:可以以字符为单位操作数据的输入和输出的对象所属的类型

2、分类:

        字符输入流  Reader

        字符输出流  Writer

 

Reader

1、字符输入流,也是一个抽象父类,不能直接创建对象

2、方法:

  read() :读取一个字符信息,将读到的信息进行返回

  read(char[] c) :读取c.length个字符到数组中,返回的是读取的字符个数

  read(char[] c,in t offset,int len):读取一部分字符到数组中

  close() :关闭流资源

3、使用子类创建对象:FileReader

  FileReader(File file)

  FileReader(String fileName)

 

 

 

Writer

1、字符输出流,是一个抽象父类,不能直接创建对象

2、方法:

  write(int c) :写出一个字符

  write(String str) :写出一个字符串

  write(char[] cbuf) :写出一个数组中的字符

  write(char[] cbuf, int off, int len) :写出数组的一部分到目标文件

  write(String str, int off, int len) :写出字符串的一部分

  close()

3、FileWriter:文件字符输出流

  FileWriter(File file)

  FileWriter(String fileName)

4、补充:

  在创建输入流的对象时,可以指定一个布尔参数:如果参数为false或者没有写,都是替换写出信息;如果参数为true的,表示追加写出信息(之前的数据不会被替换)

 

 

 

 

字符流拷贝

1、原理:

  先使用字符输入流读取每个字符,然后使用字符输出流将读取的字符写出到另外一个文 件即可。

2、图示:

 

 

 

3、总结:

  如果需要拷贝一个文件,使用哪一个流?

    使用字节流去拷贝

  如果需要读取文件的信息查看,或者需要将信息写出,使用哪一个流?

    使用字符流

 

 

 

 

使用字符流拷贝非纯文本文件

1、纯文本文件:文件中的信息表示方式都以字符表示

2、非纯文本文件:文件中的信息不是以字符方式表示

            比如:图片  视频  音频

3、结论:不能使用字符流拷贝非纯文本文件

4、原因:

  因为非纯文本文件底层的每个字节在编码表中可能没有对应的字符;如果读取文件中的 某个字节之后,在解码的时候没有一个字符与之对应,那么就会使用一个?来代替,一    旦使用?代替之后,表示数据已经发生了改变,那么再写出信息时,写出的是?对应的   字节,就导致读取的字节和写出的字节不一致。然后目标文件中的数据就拷贝失败。

 

高效缓冲字符流

1、类型:BufferedReader和BufferedWriter

2、概述:都是包装类型,需要对基础的字符流对象进行包装。包装之后,一次也可以读取多个字  符,可以写出多个字符。

3、构造:BufferedReader(Reader in)

方法:readLine() :一次可以从输入流中读取一行信息

                 返回值就是读取的这一行数据,如果到达文件的末尾,返回null

4、构造:BufferedWriter(Writer out)

方法:newLine() :表示在文件中进行换行

 

 

 

 

 

 

转换流

1、在不同的编码表中,不同的字符占用的字节不同

2、在utf-8编码表中,一个英文占用一个字节,一个中文占用三个字节

3、在gbk编码表中,一个英文占用一个字节,一个中文占用两个字节

转换输入流和转换输出流

1、OutputStreamWriter:转换输出流,在输出数据时,可以指定编码格式

        构造方法:

   OutputStreamWriter(OutputStream in, String cs) :使用基础的输出流对象,指定以cs编码格式来写出信息

 

2、InputStreamReader:转换输入流,在输入数据时,可以指定编码格式

  InputStreamReader(InputStream in, String cs) :使用基础的输入流对象,指定以cs编码格式读取信息

3、总结:

  (1)在读取信息时,以源文件的编码格式读取信息

  (2)在写出信息时,以目标文件的编码格式写出信息

  (3)使用前提:当读取或者写出信息时,文件的格式和当前代码文件格式不对应时

  (4)转换流属于字符流

 

 

 

 

 

 

 

 

 

对象序列化流

1、相关概念:

(1)数据的状态:

     游离态:在运行内存中的运行的数据。随着程序的结束,数据也会被回收。

     持久态:在磁盘中进行保存的数据。随着程序的结束,随着计算机的关机和开机,数据并不会消失。

(2)序列化:(输出)

           将数据从运行内存中 ===> 到磁盘中

           数据从游离态===>持久态

(3)反序列化:(输入)

         将数据从磁盘中 ===> 到运行内存中

           持久态===>游离态

2、对象序列化流的使用:

        构造方法:

        ObjectOutputStream(OutputStream out):将一个输出流,封装为一个对象序列化流

   序列化对象方法:

      writeObject(Object obj):将指定对象写出到流中传输

注意:

   (1)如果某个类型的对象想要实现序列化或者反序列化,那么该类型需要实现Serializable接口,否则无法完成输入和输出。

   (2)Serializable属于一个标记型接口,该接口中没有任何抽象方法需要重写,就是用来标记该类型可以实现序列化和反序列的操作。

   (3)序列化一个对象之后,该对象在文件中保存的内容看不懂。

3、反序列化流的使用:

        构造方法:

        ObjectInputStream(InputStream inp):将一个输入流,封装为一个对象序列化流

        反序列化对象方法:

        readObject():将对象从文件中读取到内存中

补充

1、如果再读取对象的时候,文件中已经没有数据,还继续读取,就会出现一个异常:

  java.io.EOFException 文件到达末尾异常

2、如果需要写出多个对象时,一般情况将多个对象保存再一个集合中,将集合对象写出一次即可,因为只写出一个集合对象,以后再读取时,也只需要读取一次即可,再遍历集  合就可以获取每一个对象了。

3、问题:在写出一个对象之后,将对象所属的类型进行了修改,然后就不能继续使用该类型接收文件中的对象了。

      解决:在写出对象之前,在类型中给定一个固定的UID:serialVersionUID

      一旦给定一个固定的id之后,类型随意修改,都可以接收对象

 

 

 

 

 

 

代码

 

 

 

 

 

 

 

 

 

 

transient关键字

1、在实现对象的序列化和反序列化时,如果某些特定的属性不需要参与,就可以通过关键字:transient来修饰该属性,一旦属性被关键字修饰之后,就不参与读取和写出。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @   晴天般的微  阅读(129)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示

目录导航