A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 卞建彬 中级黑马   /  2018-9-28 16:54  /  685 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


day09 字节流 字符流 Properties
IO


IO的概念和分类

IO流: 输入(Input)输出(Output)流
流: 数据流

输入: 从硬盘(文件)读取到内存(Java程序)
输出: 从内存(Java程序)写入到硬盘(文件
)
    (入和出都是相对于内存来说的
)
   
IO流的分类
:
    字节流 (读写字节: byte, 可以读写所有类型的文件, 包括视频, 图片, 音频, 文本等
)
        字节输入流: java.io.InputStream 抽象类

        字节输出流: java.io.OutputStream 抽象类
    字符流 (读写字符: char, String, 只能读写文本文件)
        字符输入流: java.io.Reader 抽象类

        字符输出流: java.io.Writer 抽象类


     
      
输入流
   
   
   
输出流
   
  
    
字节流
    
  
字节输入流 InputStream
  
  
  
字节输出流 OutputStream
  

    
字符流
    
  
字符输入流 Reader
  
  
  
字符输出流 Writer
  

字节流


计算机中一切皆为字节


计算机中, 无论文本, 视频, 音频, 图片... 一切都是以"字节byte"形式存储的
也就是以数字形式存储的, 而数字可以用不同进制表示, 计算机能看懂的是二进制数字


字节输出流: OutputStreamFileOutputStream


java.io.OutputStream抽象类: 字节输出流 (顶层类)
    // 成员方法

    void close() :释放资源
    void flush() :刷新缓冲区(对于字节流来说没有作用)
    // 写字节的成员方法

    abstract void write(int b): 一次写一个字节 (参数int便于传递byte的整数不用强转)
    void write(byte[] b): 一次写一个字节数组

    void write(byte[] b, int offset, int len): 一次写一个字节数组的一部分
   
java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
    // 构造方法

    FileOutputStream(String name): 通过文件路径创建文件字节输出流
    FileOutputStream(File file): 通过File对象创建文件字节输出流
    构造方法的作用:
        1. 创建一个FileOutputStream对象

        2. 根据构造方法传递的路径, 在磁盘上创建一个空文件 ("如果文件存在则会清空数据")
        3. 将创建的FileOutputStream对象指向这个磁盘上的文件


字节输出流: 一次写一个字节到文件


写数据的原理:
    Java程序 -> JVM虚拟机 -> OS操作系统 -> OS调用写数据的方法 -> 将数据写入文件

   
使用字节输出流写数据到文件的步骤:
    1. 创建对象: 创建FileOutputStream对象, 构造方法中传递文件路径

    2. 写入数据: 使用FileOutputStream对象调用 write(int b) 方法, 将字节写入文件
    3. 释放资源: 使用FileOutputStream对象调用 close() 方法, 关闭流对象释放资源
   





文件存储原理和记事本打开文件的原理

向文件中写入字节数据时, 十进制的数字会被转换为"二进制"的数字写入文件

文本编辑器打开文本文件时, 会先查询编码表, 将二进制数字转换为对应的字符进行显示
    0-127: 查询ASCII码表  -128~127
    其他: 查询系统默认码表
            Windows简体中文系统的程序打开是按 GBK 码表

            IDEA中使用的是 UTF-8 码表   

ASCII编码表: 1个byte就是一个字符
  
GBK编码表:   2个byte数字组成一个汉字.
UTF-8编码表: 3个byte数字组成一个汉字.


字节输出流: 一次写多个字节

补充:
java.lang.String类
:
    byte[] getBytes(): 使用平台的默认字符集将此String编码为byte数组

java.io.FileOutputStream类: 文件字节输出流 (向文件写数据)
    void write(byte[] b): 一次写一个字节数组

    void write(byte[] b, int off, int len): 一次写一个字节数组的一部分
   
   
   
Java中, byte的范围是 -128 ~ 127 共256个数值
编码表中字符范围是      0 ~ 255 共256个数值
   
写多个字节时:
    如果第一个字节是正数中的 0~127, 则记事本会查询 ASCII码表 显示字符

    如果第一个字节是负数中的:-128~-1, 则记事本会查询 GBK码表 显示字符.(将两个连续的byte组合为一个中文)




字节输出流: 续写, 换行


java.io.FileOutputStream类: 文件字节输出流
    // 带有 续写 功能的构造方法, 不会清空文件
    FileOutputStream(String name, boolean append): 通过文件路径创建流, true可以续写
    FileOutputStream(File file, boolean append): 通过File对象创建流, true可以续写
   
换行符:
    Windows系统: "\r\n"

    Linux系统: "\n"
    MacOS系统: "\r"



字节输入流: InputStreamFileInputStream


java.io.InputStream抽象类: 字节输入流 (顶层类)
    // 常用成员方法

    void close(): 释放资源
    // 读数据的方法
    int read(): 一次读一个字节
        读到文件末尾返回-1 (返回int也是为了代码编写方便)
    int read(byte[] b): 一次读一个字节数组

        读到的字节存放在参数中的字节数组中, 返回int值是本次读到的字节的个数. 读到文件末尾返回-1

   
java.io.FileInputStream类: 文件字节输入流
    // 构造方法
    FileInputStream(String name): 使用文件路径创建文件字节输入流
    FileInputStream(File file): 使用File对象创建文件字节输入流
    构造方法的作用:
        1. 创建FileInputStream对象

        2. 将FileInputStream对象指向磁盘上的文件





字节输入流: 一次读取一个字节


Java程序从文件读取数据的原理:
    Java程序 -> JVM虚拟机 -> OS(操作系统) -> OS调用读取的方法 -> 读取磁盘文件数据

   
java.io.InputStream抽象类: 字节输入流 (顶层类)
    int read(): 一次读一个字节

        读到文件末尾返回-1 (返回int也是为了代码编写方便)
   

   
FileInputStream读数据步骤:
    1. 创建FileInputStream对象

    2. 使用FileInputStream对象, 调用 int read() 方法, 一次读取一个byte
    3. 释放资源
   


字节输入流: 一次读取一个字节原理


字节输入流: 一次一个字节数组



补充:
java.lang.String类
:
    String(byte[] bytes): 使用平台默认字符集解码将byte数组转换为String

    String(byte[] bytes, int offset, int length): 使用平台默认字符集将数组一部分转换为String

java.io.InputStream抽象类: 字节输入流 (顶层类)
    int read(byte[] b): 一次读一个字节数组

        参数 byte[] b 作用: 存储每次读到的字节, 起到缓冲作用
        返回值作用: 每次读到的字节个数, 读到文件末尾返回-1


   




字节流复制图片文件

如何通过 FileInputStream 和FileOutputStream 实现文件复制

文件复制的步骤:
    1.创建一个字节输入流对象,构造方法中绑定要读取的数据源

    2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
    3.使用字节输入流对象中的方法read读取文件
    4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中
    5.释放资源
   
    // 创建输入流和输出流
    FileInputStream fis = new FileInputStream("c:\\1.jpg");   //输入流指向要读的数据源文件
    FileOutputStream fos = new FileOutputStream("d:\\1.jpg"); //输出流指向要写的目的地文件
    // 一次读写一个字节数组
    byte[] bytes = new byte[1024];
    int len = 0
;
    while((len = fis.read(bytes))!=-1
){
        fos.write(bytes,0,len
);
   
}
    // 释放资源

    fos.close();
    fis.close
();


字节流读取中文问题


GBK编码中, 一个汉字占用2个byte
UTF-8编码中, 一个汉字占用3个byte


字符流


字符输入流: ReaderFileReader


注意: 字符流只能读写"文本文件"

java.io.Reader抽象类: 字符输入流 (顶层)
    // 常用成员方法

    void close() :关闭此流并释放与此流相关联的任何系统资源
    // 读
    int read(): 一次读一个字符char, 返回读到的字符.
       读到文件末尾返回-1  (返回int为了代码编写方便
)
    int read(char[] cbuf): 一次读取一个字符数组char
[]
        返回读取的字符个数. 读到文件末尾返回-1

   
java.io.FileReader类: 文件字符输入流
    // 构造方法
    FileReader(File file): 根据File对象创建文件字符输入流
    FileReader(String fileName): 根据File对象创建文件字符输入流
    构造方法的作用:
        1. 创建FileReader对象

        2. 将FileReader对象指向磁盘上的文件



字符输入流: 2种方式读取文本文件


java.io.Reader抽象类: 字符输入流 (顶层)
    int read(): 一次读一个字符char, 返回读到的字符
.
       读到文件末尾返回-1  (返回int为了代码编写方便
)
    int read(char[] cbuf): 一次读取一个字符数组char
[]
        返回读取的字符个数. 读到文件末尾返回-1

   
java.lang.String类:
    String(char[] value): 将char数组转换为String

    String(char[] value, int offset, int count): 将char数组的一部分转换为String






字符输出流: WriterFileWriter


java.io.Writer抽象类: 字符输出流 (顶层类)  
   // 常用成员方法
    abstract void close(): 刷新缓冲区并释放资源
    abstract void flush() :刷新缓冲区
    // 写
    void write(int c): 写一个字符 (int类型为了代码编写方便)
    void write(char[] cbuf): 写一个字符数组

    abstract void write(char[] b, int off, int len): 写一个字符数组的一部分
    void write(String str): 写一个字符串
    void write(String str, int off, int len): 写一个字符串的一部分
    注意: write()方法只是将数据写到内存缓冲区, 最后必须调用flush()或close()才能将数据真正写入磁盘

java.io.FileWriter类: 文件字符输出流
    // 构造方法
    FileWriter(File file): 通过File对象创建文件字符输出流
    FileWriter(String fileName): 通过文件路径创建文件字符输出流
    作用:
        1. 创建FileWriter对象

        2. 根据构造方法中的路径, 在磁盘上创建文件 ("如果文件已存在, 则清空文件内容")
        3. 将FileWriter对象指向磁盘上的文件


字符输出流: 一次写一个字符


void write(int c): 写一个字符 (int类型为了代码编写方便)

FileWriter使用步骤
:
    1.创建FileWriter对象, 构造方法中绑定要写入数据的目的地

    2.使用FileWriter中的方法 write(), 把数据写入到"内存缓冲区"中(字符转换为字节的过程)
    3.使用FileWriter中的方法 flush(), 把内存缓冲区中的数据,"刷新到文件中"

    4.释放资源 close() (会先把内存缓冲区中的数据刷新到文件中)





字符输出流: flushclose区别


区别:
    flush(): 刷新缓冲区 (将数据从内存中写入到磁盘
)
    close(): 刷新缓冲区, 并释放资源. 关闭流后不能再用同一个流对象操作


flush()可以省略, 只用close()来刷新并释放资源


字符输出流: 其他方法


写的其他方法:
    void write(char[] cbuf): 写一个字符数组

    abstract void write(char[] b, int off, int len): 写一个字符数组的一部分
    void write(String str): 写一个字符串
    void write(String str, int off, int len): 写一个字符串的一部分


字符输出流: 续写, 换行


FileWriter中带有续写功能的构造:
    FileWriter(File file, boolean append): 通过File对象创建流. 第二个参数为true可以续写

    FileWriter(String fileName, boolean append): 通过文件路径创建流. 第二个参数为true可以续写
   
换行:
    windows: "\r\n"  


补充:


字节流 和 字符流 如何选择:
    1. 如果不确定读写的是什么类型的数据, 用字节流最通用

    2. 如果确定读写的就是文本, 用字符流最方便


IO异常处理


IO流操作中的异常处理

IO流使用try catch的标准格式

    FileWriter fw = null;
    try
{
        //IO流对象的创建, 操作等代码

        fw = new FileWriter("d:\\09_IOAndProperties\\g.txt", true);
        for (int i = 0; i <10 ; i++
) {
           fw.write("HelloWorld"+i+"\r\n"
);
        }
   } catch (IOException e
) {
        e.printStackTrace
();
   } finally
{
        // 释放资源

        if(fw != null){
           try
{
               fw.close
();
            } catch (IOException e
) {
               e.printStackTrace
();
            }
        }
   }





JDK7JDK9IO异常处理的不同方式


JDK 7 增加的 "try-with-resource"
    省略了 finally, 可自动释放资源
   
    // 格式
    try (创建流对象语句,如果多个,使用';'隔开) {
        // 读写数据   

    } catch (IOException e) {
        e.printStackTrace
();   
   
}
   

   
JDK 9 对于"try-with-resource"的改进
:
    流对象的声明和创建可以放在括号外面

    流对象要求是有效final的.(即不要修改流对象的值)

         FileWriter fw = new FileWriter("fw.txt"
);
    FileReader fr = new FileReader("fr.txt"
);
    try (fw; fr
) {
        // IO操作

        int ch = fr.read();
        fw.write(ch
);
   } catch (IOException e
) {
        e.printStackTrace
();
   }


Properties集合


Properties存储数据和遍历

Properties双列集合有哪些特有方法

Properties双列集合:
    键和值都是 String 类型


java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable
    // 构造方法
    Properties(): 创建一个Properties集合
    // 可以使用Map接口中的方法
    // 特有成员方法
    Object setProperty(String key, String value): 保存/替换键值对
    String getProperty(String key): 通过键获取值. 键不存在返回null
    Set<String> stringPropertyNames(): 返回键的集合
    void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
    void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文),并写入注释
    void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
    void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)



Properties: store()存储数据到文件


Properties将数据写入到文件的方法:
    void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释

    void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文), 并写入注释
   
使用步骤:
    1.创建Properties集合对象,添加数据

    2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
    3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
    4.释放资源

属性集(配置文件), 标准的后缀是.properties
配置文件格式要求:
    一行一个键值对

    键和值中间用=分隔 (标准格式, 但空格分开也行)
    #表示单行注释


Properties: load()从文件加载数据到集合


Properties将数据从文件加载到集合中的方法:
    void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文
)
    void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文
)
        
使用步骤
:
    1.创建Properties集合对象

    2.使用Properties集合对象中的方法load读取保存键值对的文件





0 个回复

您需要登录后才可以回帖 登录 | 加入黑马