字符流

#day12-IO(字符流、Properties)
***
##1. 字符流引入
    1. 使用字节流读写字符数据产生的问题
        1. 问题1 : 如果写出的是字符数据, 需要将字符数据转换成字节数组. 
        2. 问题2 : 如果使用字节流读取中文数据, 发生了 `乱码`. 4
    
    2. 集成电路
        1. Cpu、内存、硬盘、IO输入输出硬件设备,都是属于集成电路
        2. 电子元件 : 只有两种状态,要么开要么关(1和0)
        3. 集成电路就是无数个电子元件组合起来的
        4. 例子
            1. 01001001,8位  -》b  -》 ASCII码(1个字节,首位是0,只用7位,故表示128个)
            2. encode(编码): 汉语 -> 0101   编码,之后方便计算机存储
            3. decode(解码): 0101 -> 汉语   解码,之后方便人类查看
            4. messy code(乱码) : 用一种A编码表编码,用B编码表解码

    3. 编码表介绍
        1. 字节转成字符的规则
        2. ascii码表,128个,占一个字节:8位,首位是0,后7位表示  (1个字节)
        3. ISO-8859-1(欧码)256个,占一个字节:8位全表示        (1个字节)
        4. gbk 2个字节表示1个汉字(windows系统默认)    
        5. utf8  3个字节表示1个汉字(Java开发主流)
##2. 字符流体系
     1. 便捷字符输入流:FileReader
         0. 需求:使用便捷字符输入流解决了读取中文乱码的问题 
         1. 字符流 : 字节流 + 编码表 (字节转字符的规则)                    
            2. FileReader 读取字符文件的便捷类.  
            3. 特点 : 使用简单,使用该类无需指定编码表
            4. 问题: 底层到底有没有编码表??? 有的和平台默认使用编码表一致,GBK
 
    2. 便捷字符输入流:FileWriter
        0. 使用便捷字符输出流写入英文与中文到文件中 
        1. 写出数据时, 字符串无需转换.
        2. 写出时无需创建File对象, 也无需指定编码表. 内部使用默认编码表.

    3. 字符转换输出流:OutputStreamWriter
        0. 需求 : 使用 GBK & UTF-8 写出 hello,我的女神,I love you."
        1. OutputStreamWriter(OutputStream out, String charsetName) 使用指定字符集
        2. 是字符流通向字节流的桥梁    字符流 = 字节流 + 编码表
        3. 字符流的底层是调用字节流读写
        4. 多种方式
            0. FileWriter writer = new FileWriter(path); 
            1. new OutputStreamWriter(FileOutputStream fos);
            2. OutputStreamWriter(OutputStream out, String charsetName)

    4. 字符转换输入流:InputStreamReader
        0. 使用InputStreamReader 读取不同编码的文件(GBK、UTF-8)
        1. 多种方式
            0. FileReader reader = new FileReader(path);
            1. InputStreamReader(InputStream in) 创建一个使用默认字符集
            2. InputStreamReader(InputStream in, String charsetName) 使用指定字符集

    5. 编解码和乱码
        1. 编码 encode:将字符数据转换成字节数据. 目的:将字符数据以字节的形式存储到硬盘文件中.
        2. 解码 decode:将字节数据转换成字符数据. 目的:将文件中的字节数据转换为字符给程序员查看.
        3. 乱码 messy code:以A编码表进行编码, 以B编码表进行解码, 结果就是乱码. (编码表和解码表对应不上就会产生乱码)

##3. 复制文件原理
    1. 复制文件的方式
        1. Reader & Writer 字符流复制文本文件 :
            1. FileReader & FileWriter (使用环境默认编码)
            2. InputStreamReader & OutputStreamWriter (手动指定)
        2. inputStream & 0utputStream
            1. fileInputStream & fileOutputStream
        
    2. 问题:既然字节流和字符流都能复制文件,那它们有何区别?

    3. 原理:
        1. 字符流在复制过程中需要先编码后解码,效率低。而且在复制图片和音视频文件时也因为编解码的原因,容易造成复制之后的文件产生问题。
        2. 字节流复制过程没有编解码,效率高,而且不出错
    4. 总结
        1. 文件复制应该用字节流 
        2. 字符流应该用来读写字符数据
## 4. 字符缓冲流
1. BufferedReader & BufferedWriter字符缓冲流
    1.  BufferedWriter : 接收 Writer.
        1. FileWriter(GBK)-> 接收 String / File
         2. OutputStreamWriter (UTF-8)-> 接收 OutputStream-> 传递FileOutputStream -> 接收 String / File
         3. 缓冲流写出三部曲
             1. 写出     2. 换行    3. 刷新 
     2.  BufferedReader -> 接收 Reader
         1. FileReader(GBK)    -> 接收 String / File
         2. InputStreamReade(UTF-8)-> 接收 InputStream -> 传递 FileInputStream -> 接收 String / File 
## 5. 其它流
    1. 打印流
        1. PrintStream
            1. printStream 无需手动关闭和刷新, 数据也可以写入到文件中 (自动刷新)
            2. PrintStream 为其他输出流添加了功能,使它们能够 `方便地打印各种数据值  print / println` 表示形式。

        2. PrintWriter
            1. PrintWriter 需要 `启动自动刷新`.
            2. 使用场景:网络请求 -> request 请求  PrintWriter writer = request.getPrintWriter();  作用: 向网页中写出数据.

    2. 序列化和反序列化
        0. 需求:将一个自定义对象存储到文件中, 并读取出来.
        1. 概念
            1. 序列化 :将数据结构或对象转换成二进制串的过程
             2. 反序列化 :二进制串转换成数据结构或者对象的过程
        2. ObjectOutputStream:将Java的对象写入到文件中
            1. 异常:NotSerializableException 不能序列化异常
            2. 解决:类通过实现 java.io.Serializable 接口以启用其序列化功能
            3. Serializable接口
                1. 当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口
                2. 如果一个接口中没有任何方法, 那么该接口就被称为 `标识接口`
        3. ObjectInputStream:将文件中的数据读取为 Java 对象.
            1. 异常:InvalidClassException 非法类异常(修改该类)
            2. 原因如下:
                1. 该类的序列版本号与从流中读取的类描述符的版本号不匹配 
                2. 该类包含未知数据类型 
                3. 该类没有可访问的无参数构造方法 
            3. Serializable标记接口。该接口给需要序列化的类,提供了一个序列版本号serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。
            4. 解决:在类中显示声明一个该对象的 UID 序列号
                * 自动生成,根据该类所有数据计算
        4. 瞬态关键字transient
            1. 只要被transient修饰的属性,在对象序列化时,这个属性不会被序列化

        5. 练习和应用
            1. 练习:集合(四大名著:作者) 进行序列化和反序列化
            2. 应用:
                1. 序列化这个概念太笼统,说白了就是方便计算机表述,使用010101的方式方便传输和存储。
                2. java 序列化 也是为了 传输和存储,只是 Serializable 是使用java内部序列化格式。开发中,由于java自身的序列化信息不够简洁,一般很少有使用java 序列化对象进行通信的。
##6. Properties类
    1. Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
    2. 特点:
        1. Hashtable的子类,map集合中的方法都可以用。
        2. 该集合没有泛型。键值都是字符串。
        3. 它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。键值的来源也可以是持久化的设备。
        4. 有和流技术相结合的方法。
    3. 方法:
        1. setProperty(String key, String value):调用 Hashtable 的方法 put
        2. stringPropertyNames()返回此属性列表中的键集
        3. getProperty(String key)用指定的键在此属性列表中搜索属性
        
        4. store(Writer,comments)和 store(OutputStream,comments)
            1. 把集合中的数据,保存到指定的流所对应的文件中,参数comments代表对描述信息
        5. load(InputStream) 和load(Reader) 
            1. 把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中

    4. 获取本地系统的属性集
        1. Properties prop = System.getProperties() 所有属性集
        2. String country = System.getProperty("user.country") 单个属性集

##8. Commons-IO 第三方开源包
    1. Apache 软件基金组织 : Commons-IO      `通用 IO 包`
    2. JAR包
        1. (Java Archive,Java 归档文件)是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件。
        2. .jar 文件 : 集成了 class 文件. -> class 文件的压缩包.
    3. 导开源包的步骤
        1. 在工程下创建一个lib文件夹(跟src平级)
        2. 复制 .jar文件到lib目录
        3. 选中jar包 右单击  -》 build path
    4. FileUtils 类 :
        1. static void copyFile(File srcFile, File destFile);    复制文件
        2. static void copyDirectoryToDirectory(File srcDir, File destDir).复制文件夹
## 9. 流总结
    1. "字节流 :"
        1. InputStream : 字节输入流
          |-- FileInputStream
          |-- BufferedInputStream    8k缓存 byte[]
        2. OutputStream : 字节输出流
          |-- FileOutputStream
          |-- BufferedOutputStream

    2. "字符流 :"
        1. Reader : 字符输入流
            |-- InputStreamReader : InputStream + 任意编码表
                |-- FileReader : InputStreamReader + 默认编码表 (便捷类) 字节流 + 编码表
            |-- BufferedReader
        2. Writer : 字符输出流 
            |-- OutputStreamWriter : OutputStream + 任意编码表
                 |-- FileWriter : OutputStreamWriter + 默认编码表 (便捷类)字节流 + 编码表
            |-- BufferedWriter

    3. "请问 : 如何选择使用那种流呢?"    
        1. "问题1 : 读取字节数据还是字符数据?"
            1. 字节 : BufferedInputStream / BufferedOutputStream
            2. 字符 : BufferedReader / BufferedWriter
        2. "问题2:复制文件用什么流?"
            1. 字节流:因为字符流需要编解码,效率低,而且可能出错。
        3. "问题3 : 我是读还是写?"
            1. 读 : BufferedInputStream / BufferedReader
            2. 写 : BufferedOutputStream / BufferedWriter
        4. "问题4 : 是否需要高效缓冲呢 ?" 当然要.
            1. 是 : 就用对应体系的缓冲流包起来. 缓冲流就是用来装饰其它流的.所以,要加缓冲,就用缓冲流包装其它流
        5. "问题5 : 是否需要指定编码表?"
            1. 需要 , 转换流. OutputStreamWriter & InputStreamReader
            2. 不需要 , 便捷流. FileWriter & FileReader(默认编码)

## 快捷键
1. 程序崩溃, windows -》ctrl + alt + delete -> 任务管理器 -》结束任务
2. 程序失去响应 -》 底部 ,右单机-》启动任务管理器


 

转载于:https://my.oschina.net/u/3892666/blog/2250928

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值