java学习(七)之转换/序列/打印流

今日学习

转换流

编码/解码:

  • 编码:将字符按某种规则存储到计算机中
  • 解码:存储在计算机中的二进制数据按某种规则解析显示

字符集(编码表):生活中问庄子与计算机中二进制的对应规则
例如:ASCIIGBKUNICODE(UTF-8UTF-16UTF-32)

字符集

  1. ASCII基于拉丁字母,显示:英语、控制字符、数字等
    1. 基本ASCII:7位表示一个字符->128个
    2. 扩展ASCII:8位表示一个字符->256个
  2. ISO-8859-1显示欧洲语言,单字节编码,兼容ASCII编码
  3. GBK显示中文
    1. GB2312简体中文表,兼容ASCII编码
    2. GBK最常用的编码表,双字节编码,兼容ASCII编码,支持繁体、日韩文字等
    3. GB18030最新的编码表,多字节,支持少数民族文字、繁体、日韩
  4. UNICODE万国码,最多用4个字节表示
    1. UTF-8:128个 ASCII,占1个字节;拉丁文,占2个字节;大部分(含中文),占3个字节;其他极少用,占4个字节
    2. UTF-16
    3. UTF-32
乱码问题

FileReader读取windows系统创建文本文件(中午系统默认GBK),容易引发乱码问题
原因:FileReader只能读取IDEA默认编码(UTF-8)的文件
注意:FileReader底层调用FileInputStream读取字节

转换流

OutputStreamWriter

java.io.OutputStreamWriter extends Writer将字符流按指定的charset转换为字节流(编码)

  1. 构造方法

    1. OutputStreamWriter osw = new OutputStreamWriter(OutputStream out);按默认编码表转换
    2. OutputStreamWriter osw = new OutputStreamWriter(OutputStream out, String charsetName);按指定编码表转换
      注意:charsetName不区分大小写!
  2. 使用步骤

    1. 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表
    2. 调用write()方法,将字符流按指定编码转换为字节流存储到内存缓冲区中
    3. 调用flush()方法,将缓冲区的数据刷新到文件中(可省略)
    4. 调用close()方法,关闭输出流,释放资源
InputStreamReader

java.io.InputStreamReader extends Reader将字节流按指定的charset转换为字符流(解码)

  1. 构造方法

    1. InputStreamReader isr = new InputStreamReader(InputStream in);按默认编码表转换
    2. InputStreamReader osw = new InputStreamReader(InputStream in, String charsetName);按指定编码表转换
      注意:charsetName不区分大小写!
  2. 使用步骤

    1. 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表
    2. 调用read()方法,将字节流按指定编码转换为字符流,读取
    3. 调用close()方法,关闭输入流,释放资源
      注意:构造方法中指定的编码必须与待读取文件的编码一致,否则会出现乱码问题

序列化和反序列化

序列化

将对象以流的形式写入到文件中,即写对象,也叫对象的序列化
注意:对象中包含的不仅仅有字符,所以要用字节流
java.io.ObjectOutputStream extends OutputStream

  1. 构造方法:ObjectOutputStream oos = new ObjectOutputStream(OutputStream out);
  2. 特有方法:void writeObject(Object o);
  3. 使用步骤:
    1. 创建ObjectOutputStream对象,构造方法中传递字节输出流对象
    2. 调用writeObject方法将对象序列化写入文件中
    3. 调用close方法释放资源

反序列化

将文件保存的对象数据,以流的形式读取出来,即读对象,也叫对象的反序列化
注意:文件中保存的不仅仅有字符,所以要用字节流
java.io.ObjectInputStream extends InputStream

  1. 构造方法:ObjectInputStream ois = new ObjectInputStream(InputStream in);
  2. 特有方法:Object readObject();
  3. 使用步骤:
    1. 创建ObjectInputStream对象,构造方法中传递字节输入流对象
    2. 调用readObject方法读取文件中的对象
    3. 调用close方法释放资源
      注意:readObject方法声明中抛出ClassNotFoundExceptionclass文件找不到异常),当不存在对象的class文件时会抛出此异常
      实现反序列化的前提:
      1. 实现Serializable接口
      2. 必须存在类对应的class文件

抛出异常

  1. NotSerializableException没有序列化异常
    序列化和反序列化时会抛出NotSerializableException异常,类通过实现java.io.Serializable接口以启用其序列化功能。
    注意:要进行序列化/反序列化的类必须实现java.io.Serializable接口,给类加一个标记
    当进行序列化/反序列化时,会检测类是否有这个标记:
    • 有:进行操作
    • 无:抛出NotSerializableException异常
  2. ClassNotFoundException
    readObject方法声明中抛出ClassNotFoundExceptionclass文件找不到异常),当不存在对象的class文件时会抛出此异常
  3. InvalidClassException无效类异常
    JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生改变,则反序列化就会失败,抛出异常。
    javac.exe会把类java文件编译为对应的class文件,此类实现了Serializable接口,会根据类的定义给class文件中添加序列化号serialVersionUID再进行反序列化时,会验证class文件与序列化后的文件的序列号:
  • 相同,反序列化顺利执行 ;
  • 否则,会抛出InvalidClassException
    解决方法:在序列化/反序列化的类中定义成员变量设置序列号private static final long serialVersionUID = 任意值L;

瞬态关键字

`瞬态关键字``transient:被它修饰的成员变量不能被序列化 静态关键字static```:优先于非静态加载到内存中,也不能被序列化

文件中保存多个对象

分析:

  1. 创建一个集合,保存多个对象
  2. 对集合进行序列化

打印流

java.io.PrintStream extends OutputStream

  1. 特点
    1. 只负责数据输出
    2. 用于不会抛出IOException
    3. 存在特有的方法:print()/prntln()可以输出任意类型的数据
  2. 构造方法
    1. PrintStream(File file),目的地是文件
    2. PrintStream(OutputStream out),目的地是输出流
    3. PrintStream(String fileName),目的地是文件路径
  3. 注意
    若使用继承自父类的write()方法写数据,那么查看数据会查询编码表
    如使用特有方法print()/println()方法,那么原样输出
  4. System的静态方法static void setOut(PrintStream ps)重新分配“标准”输出流
    格式:
    //将输出内容写道打印流中,而非控制台
    PrintStream out  = new PrintStream(file);
    System.setOut(out);
    System,out.println("你好");
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值