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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 养只猫叫冰棍儿 初级黑马   /  2018-11-26 16:06  /  750 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Day9
IO流
        字节流 (输入流读, 输出流写) byte byte[]
        字符流 (输入流读, 输出流写) char char[] String
        异常处理 (通用格式, JDK7优化格式, JDK9优化格式)
Properties双列集合
        存取数据
        读写到文件
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
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() 方法, 关闭流对象释放资源
       
        FileOutputStream fos = new FileOutputStream("模块名\\文件名.txt");
        fos.write(97);
        fos.close();
向文件中写入字节数据时, 十进制的数字会被转换为"二进制"的数字写入文件
文本编辑器打开文本文件时, 会先查询编码表, 将二进制数字转换为对应的字符进行显示
        0-127: 查询ASCII码表  -128~127
        其他: 查询系统默认码表
                        Windows简体中文系统的程序打开是按 GBK 码表
                        IDEA中使用的是 UTF-8 码表   
ASCII编码表: 1个byte就是一个字符  97 a
GBK编码表:   2个byte数字组成一个汉字. "你": -60, -29
UTF-8编码表: 3个byte数字组成一个汉字. "你": -28, -67, -96
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"
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. 释放资源
       
        FileInputStream fis = new FileInputStream("模块名\\文件名");
        // 一次读一个字节:
        int by;   // int变量用来存储每次读到的数据
        while (   (  by = fis.read()  ) != -1    ) {
                System.out.print((char)by);  // 不要换行, 文件中自带换行的byte
        }
        fis.close();
java.io.InputStream抽象类: 字节输入流 (顶层类)
        int read(byte[] b): 一次读一个字节数组
                参数 byte[] b 作用: 存储每次读到的字节, 起到缓冲作用
               
   
// 示例代码
FileInputStream fis = new FileInputStream("模块名\\文件名");
byte[] bytes = new byte[1024];  // 定义字节数组, 用于保存每次读取到的数据
int len;                        // 定义int变量, 用于保存每次读取到的长度
while ((len = fis.read(bytes)) != -1) {
    String s = new String(bytes, 0, len); // 将读取到的字节转换为字符串, 读到多少个就转换多少个
    System.out.print(s);
}
fis.close(); // 释放资源
文件复制的步骤:
        1.创建一个字节输入流对象,构造方法中绑定要读取的数据源
        2.创建一个字节输出流对象,构造方法中绑定要写入的目的地
        3.使用字节输入流对象中的方法read读取文件
        4.使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中

GBK编码中, 一个汉字占用2个byte
UTF-8编码中, 一个汉字占用3个byte
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对象指向磁盘上的文件
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
// 一次读一个字符
int ch;  // 定义变量保存每次读到的字符
while ((ch = fr.read()) != -1) {
    System.out.print((char)ch);
}
// 一次读一个字符数组
char[] cs = new char[1024];
int len;
while ((len = fr.read(cs)) != -1) {
        String s = new String(cs, 0, len);
    System.out.print(s);
}
// 释放资源
fr.close();
java.io.Writer抽象类: 字符输出流 (顶层类)   'a''b'  缓冲区    97 98
        // 常用成员方法
        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对象指向磁盘上的文件

FileWriter使用步骤:
        1.创建FileWriter对象, 构造方法中绑定要写入数据的目的地
        2.使用FileWriter中的方法 write(), 把数据写入到"内存缓冲区"中(字符转换为字节的过程)
        3.使用FileWriter中的方法 flush(), 把内存缓冲区中的数据,"刷新到文件中"
        4.释放资源 close() (会先把内存缓冲区中的数据刷新到文件中)

其他write()方法可以写入什么样的数据:写的其他方法:
        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可以续写
IO流的标准格式:
        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();
            }
        }
}
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将数据写入到文件的方法:
        void store(OutputStream out, String comments): 将集合用字节流写入文件(不能中文),并写入注释
        void store(Writer writer, String comments): 将集合用字符流写入文件(可以中文), 并写入注释
       
使用步骤:
        1.创建Properties集合对象,添加数据
        2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地
        3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储
        4.释放资源
Properties将数据从文件加载到集合中的方法:
        void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
        void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)
使用步骤:
        1.创建Properties集合对象
        2.使用Properties集合对象中的方法load读取保存键值对的文件
        3.遍历Properties集合
Day10
IO流:
    缓冲流: BufferedInputStream / BufferedOutputStream, BufferedReader / BufferedWriter
        在基本流上增加缓冲区 char[] byte[], 提高读写效率
    转换流: InputStreamReader / OutputStreamWriter
            字节转字符: FileReader 读 char <- byte 硬盘
                字符转字节: FileWriter 写 char -> byte 硬盘
    序列化流: ObjectInputStream / ObjectOutputStream
            序列化:   内存中的对象 写-> 硬盘上的文件中
        反序列化: 内存中的对象 <-读 硬盘上的文件中
    打印流: PrintStream
            可以自动换行, 原样输出  System.out.println();
基本流: FileXxx
包装流:
        包装流只是在基本流的外面增加了一些便捷的功能, 最终进行读写的还是基本流
        但是包装流增强了基本流的功能
        BufferedReader br = new BufferedReader(new FileReader());
缓冲流的原理:
        底层也是使用基本流(FileXxx)来读写
        但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高了程序效率
字节缓冲流
        |_ BufferedInputStream     # 缓冲字节输入流
        |_ BufferedOutputStream    # 缓冲字节输出流
字符缓冲流
        |_ BufferedReader          # 缓冲字符输入流
        |_ BufferedWriter          # 缓冲字符输出流
       
java.io.BufferedOutputStream类: 缓冲字节输出流
        // 构造方法
        BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流
        BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大小
       
BufferedOutputStream使用步骤:
        1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地
        2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象
        3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中
        4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中
        5.释放资源(会先调用flush方法刷新数据, 第4步可以省略)
java.io.BufferedInputStream类: 缓冲字节输入流
        // 构造方法
        BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流
        BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲区大小
       
使用步骤:
        1.创建FileInputStream对象, 构造方法中绑定要读取的数据源
        2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象
        3.使用BufferedInputStream对象中的方法 read(), 读取文件
        4.释放资源 close()
java.io.BufferedWriter类:
        // 构造方法
        BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流
        BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小
        // 特有方法
        void newLine(): 写入一个换行符, 换行符自动根据当前系统确定
java.io.BufferedReader类: 缓冲字符输入流
        // 构造方法
        BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流
        BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小
        // 特有方法
        String readLine(): 一次读一行字符串, "不包含换行符". 读到文件末尾返回null
编码: 字符 -> 字节  'a' -> 97
解码: 字节 -> 字符  97 -> 'a'
编码表: 字符和二进制数字的对应规则
   
字符集和编码表: 字符集包含编码表
        ASCII字符集
                ASCII编码表
                ASCII扩展编码表
        ISO-8859-1字符集: Tomcat Web服务器程序
                Latin-1: 拉丁字符. 没有中文. 每个字符由1个byte组成
        GB字符集
                GB2312编码表: 每个字符由2个byte组成
                GBK编码表: 每个字符由2个byte组成
                GB18030编码表: 每个字符由1, 2, 4个byte组成
        Unicode字符集
                UTF-8: ASCII字符占1个byte, 拉丁字符占2个byte, 中文占3个byte, Unicode辅助字符占4个byte
                UTF-16
                UTF-32
        ANSI: 表示使用系统默认编码表
java.io.Reader
        |_ InputStreamReader: 转换字符输入流      byte --查指定码表--> char, char[], String
                |_ FileReader                       byte --查UTF-8码表--> char
java.io.Writer
        |_ OutputStreamWriter: 转换字符输出流      char, char[], String --查指定码表--> byte
                |_ FileWriter                        char --查UTF-8码表--> byte
java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁
        // 构造方法
        OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
        OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
       
// 使用默认UTF-8
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"));
o.write("dsfdsfdsaf")
// 使用指定的GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
                osw.write("你") -> 查"GBK"码表 -> -1,-2 -> FileOutputStream -> a.txt文件
         写数据: 字符流 --------------------------> 字节流
java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁
        // 构造方法
        InputStreamReader(InputStream in): 使用默认编码表创建转换流
        InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
       
// 使用默认UTF-8
InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"));
// 使用指定的GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"), "GBK");
     '你' <- 查"GBK"码表 <- isr.read() <- -1,-2 <- FileInputStream <- a.txt文件
                         读数据: 字符流 <---------- 字节流       
转换流小结:
FileReader = InputStreamReader + FileInputStream, 按照IDEA中UTF-8将读取的字节转换为字符
FileWriter = OutputStreamWriter + FileOutputStream, 按照IDEA中UTF-8将写出的字符转换为字节
转换流InputStreamReader, OutputStreamWriter在读写时, 可以指定按照哪个编码表来进行转换
所以:
字符流 = 编码表 + 字节流
转换流主要用于解决Web开发中的乱码问题
序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中
        对象 -> 字节
反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象
        字节 -> 对象
通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态
OutputStream
        |_ ObjectOutputStream类: 对象字节输出流
InputStream
        |_ ObjectInputStream类: 对象字节输入流
java.io.ObjectOutputStream类: 对象字节输出流
        // 构造方法
        ObjectOutputStream(OutputStream out)
        // 特有成员方法
        void writeObject(Object obj): 将对象写出
       
// 创建对象输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student.txt"));
// 写对象
Student s = new Student("小美女", 18);
oos.writeObject(s);
// 释放资源
oos.close();
注意:
        被读写的对象的类必须实现"java.io.Serializable"接口, 否则会抛出"NotSerializableException"
java.io.ObjectInputStream类: 对象字节输入流
        // 构造方法
        ObjectInputStream(InputStream in)
        // 特有成员方法
        Object readObject(): 读取对象
       
// 创建对象输入流
ObjectInputStream oos = new ObjectInputStream(new FileInputStream("student.txt"));
// 读对象
Object o = oos.readObject();
Student s = (Student)o;
System.out.println(s);
// 释放资源
oos.close();
static 修饰的成员变量属于类不属于对象, 所以不能序列化
transient 修饰的成员变量, 不能被序列化
transient 应用场景:
        如果对象的某个属性不希望被序列化, 可以使用 transient 修饰, 这样就不会被对象流写到文件中
serialVersionUID序列号的作用:
        序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中.
        该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化
        当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException
为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是一样的
PrintStream特点:
        1. 只有输出流, 没有输入流
        2. PrintStream不会抛出IOException
        3. 有特殊方法 print(), println(), 可以输出任意类型的值, 原样输出
java.io.PrintStream类: 字节打印流
        // 构造方法
        PrintStream(File file): 创建字节打印流, 输出到一个文件
        PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
        PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径
       
注意事项:
        如果用 write(97) 方法, 会查编码表   97 -> a
        如果用 print(97), println(97), 则原样输出  97 int -> '9''7' -> byte -> 文件 97
        System.out.println();
        PrintStream out;
       
java.lang.System类:
        // 静态方法
        static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流
// 体系结构:
字节流
        |_ InputStream                 # 字节输入流
        |        |_ FileInputStream         # 专门操作文件的字节输入流
        |        |_ BufferedInputStream     # 带有缓冲区的字节输入流, 效率高
        |        |_ ObjectInputStream       # 对象输入流
        |
        |_ OutputStream                # 字节输出流
                |_ FileOutputStream        # 专门操作文件的字节输出流
                |_ BufferedOutputStream    # 带有缓冲区的字节输出流, 效率高
                |_ ObjectOutputStream      # 对象输出流
                |_ PrintStream             # 字节打印流
字符流
        |_ Reader                      # 字符输入流
        |        |_ BufferedReader          # 带有缓冲区的字符输入流, 效率高
        |        |_ InputStreamReader       # 将字节流转换为字符流输入的转换输入流
        |                |_ FileReader          # 专门操作文件的字符输入流       
        |
        |_ Writer                      # 字符输出流
                |_ BufferedWriter          # 带有缓冲区的字符输出流, 效率高
                |_ OutputStreamWriter      # 将字符流转换为字节流输出的转换输出流
                |     |_ FileWriter         # 专门操作文件的字符输出流


0 个回复

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