本帖最后由 小石姐姐 于 2018-8-9 11:27 编辑  
 
 
 
四、Properties集合 
4.1 Properties存储数据和遍历 
    Properties双列集合: 
    键和值都是 String 类型 
    java.util.Properties类: 属性集, 属于Map的双列集合, 继承自Hashtable 
    // 构造方法 
    Properties(): 创建一个Properties集合 
    // 可以使用Map接口中的方法 
    / 特有成员方法 
   [AppleScript] 纯文本查看 复制代码  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集合(可以读中文) 4.2 Properties: store()存储数据到文件 
    Properties将数据写入到文件的方法: 
    void store(OutputStream out, String comments): 将集合数据用字节流写入文件(不能中文), 并写入注释 
    void store(Writer writer, String comments): 将集合数据用字符流写入文件(可以中文), 并写入注释 
    使用步骤: 
    1.创建Properties集合对象,添加数据 
    2.创建字节输出流/字符输出流对象,构造方法中绑定要输出的目的地 
    3.使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储 
    4.释放资源 
    补充: 
    属性集(配置文件), 标准的后缀是.properties 
    配置文件格式要求: 
    一行一个键值对 
    键和值中间用=分隔 (标准格式, 但空格分开也行) 
    [AppleScript] 纯文本查看 复制代码 #表示单行注释
    示例: db.properties
    # This is a comment!
    className=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test
    username=root
    password=123456 
4.3 Properties: load()从文件加载数据到集合 
    Properties将数据从文件加载到集合中的方法: 
   [AppleScript] 纯文本查看 复制代码  void load(InputStream inStream): 从配置文件中通过字节流加载数据到Properties集合(不能读中文)
    void load(Reader reader): 从配置文件中通过字符流加载数据到Properties集合(可以读中文)     使用步骤: 
    1.创建Properties集合对象 
    2.使用Properties集合对象中的方法load读取保存键值对的文件 
    3.遍历Properties集合 
五、加强版IO流 
5.1 缓冲流 
5.1.1 缓冲流的原理 
    缓冲流的原理: 
    底层也是使用基本流(FileXxx)来读写 
    但缓冲流内部定义了一个缓冲数组, 在读的时候类似于我们一次读一个数组的方式, 减少了磁盘操作次数, 提高了 
    程序效率 
 
 
 
5.1.2 缓冲字节输出流: BufferedOutputStream 
    字节缓冲流 
    |_ BufferedInputStream # 缓冲字节输入流 
    |_ BufferedOutputStream # 缓冲字节输出流 
    字符缓冲流 
    |_ BufferedReader # 缓冲字符输入流 
    |_ BufferedWriter # 缓冲字符输出流 
    java.io.BufferedOutputStream类: 缓冲字节输出流 
    // 构造方法 
  [AppleScript] 纯文本查看 复制代码   BufferedOutputStream(OutputStream out): 使用基本流创建一个缓冲字节输出流
    BufferedOutputStream(OutputStream out, int size): 使用基本流创建一个缓冲字节输出流, 设置缓冲区大
    小     BufferedOutputStream使用步骤: 
    1.创建FileOutputStream对象, 构造方法中绑定要输出的目的地 
    2.创建BufferedOutputStream对象, 构造方法中传递FileOutputStream对象, 提高FileOutputStream效率 
    3.使用BufferedOutputStream对象中的方法 write(), 把数据写入到内部缓冲区中 
    4.使用BufferedOutputStream对象中的方法 flush(), 把内部缓冲区中的数据,刷新到文件中 
    5.释放资源(会先调用flush方法刷新数据, 第4步可以省略) 
   [AppleScript] 纯文本查看 复制代码  FileOutputStream fos = new FileOutputStream("文件路径");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    bos.write("你好".getBytes());
    // bos.flush(); // 可以省略
    bos.close(); 
5.1.3 缓冲字节输入流: BufferedInputStream 
    java.io.BufferedInputStream类: 缓冲字节输入流 
    // 构造方法 
    BufferedInputStream(InputStream in): 使用基本流创建一个缓冲字节输入流 
    BufferedInputStream(InputStream in, int size): 使用基本流创建一个缓冲字节输入流, 设置缓冲区大小 
    使用步骤: 
    1.创建FileInputStream对象, 构造方法中绑定要读取的数据源 
    2.创建BufferedInputStream对象, 构造方法中传递FileInputStream对象, 提高FileInputStream效率 
    3.使用BufferedInputStream对象中的方法 read(), 读取文件 
    4.释放资源 close() 
    [AppleScript] 纯文本查看 复制代码 FileInputStream fis = new FileInputStream("文件路径");
    BufferedInputStream bis = new BufferedInputStream(fis);
    byte[] bytes = new byte[1024];
    int len;
    while ((len = bis.read(bytes)) != -1) {
    System.out.println(new String(bytes, 0, len));
    }
    bis.close(); 
5.1.4 缓冲字符输出流: BufferedWriter  
    java.io.BufferedWriter类: 
    // 构造方法 
    BufferedWriter(Writer out): 使用基本流创建一个缓冲字符输出流 
    BufferedWriter(Writer out, int size): 使用基本流创建一个缓冲字符输出流, 设置缓冲区大小 
    // 特有方法 
    void newLine(): 写入一个换行符, 换行符自动根据当前系统确定 
5.1.5 缓冲字符输入流: BufferedReader 
    java.io.BufferedReader类: 缓冲字符输入流 
    // 构造方法 
    BufferedReader(Reader in): 使用基本流创建一个缓冲字符输入流 
    BufferedReader(Reader in, int size): 使用基本流创建一个缓冲字符输入流, 设置缓冲区大小 
    // 特有方法 
    String readLine(): 一次读一行字符串, "不包含换行符". 读到文件末尾返回null 
5.2 转换流 
5.2.1 字符编码和字符集 
    编码: 字符 -> 字节 'a' -> 97 
    解码: 字节 -> 字符 97 -> 'a' 
    编码表: 字符和二进制数字的对应规则 
    字符集和编码表: 字符集包含编码表 
    ASCII字符集 
    ASCII编码表 
    ISO-8859-1字符集: 
    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: 表示使用系统默认编码表 
 
 
 
5.2.2 乱码问题: FileReader读取GBK编码 
    乱码原因: 读写编码不一致 
    GBK文件中存储的是"你好"在GBK中对应的byte 
    而IDEA中使用FileReader读取文件时, 是将byte按照UTF-8编码表查找字符, 结果找不到, 就显示了问号 
5.2.3 乱码原理: 字符流和转换流的关系 
    java.io.Reader 
    |_ InputStreamReader: 转换字符输入流 读 char char[] byte -> char 97 -> 'a' 
    |_ FileReader byte -UTF-8-> char 
    java.io.Writer char char[] String 
    |_ OutputStreamWriter: 转换字符输出流 char char[] String -> byte 
    |_ FileWriter char -UTF-8-> byte 
    FileReader=InputStreamReader+FileInputStream, 只不过固定按照IDEA中的UTF-8来将读取的字节转换为字符 
    FileWriter=OutputStreamWriter+FileOutputStream, 只不过固定按照IDEA中的UTF-8来将写出的字符转换为字节 
    字符流 = 字节流 + 编码表 
    转换流InputStreamReader, OutputStreamWriter在读写时, 可以指定按照哪个编码表来进行转换 
5.2.4 OutputStreamWriter类介绍及使用 
    java.io.OutputStreamWriter类: 输出转换流. 字符流通往字节流的桥梁 
    // 构造方法 
    [AppleScript] 纯文本查看 复制代码 OutputStreamWriter(OutputStream out): 使用默认编码表创建转换流
    OutputStreamWriter(OutputStream out, String charsetName): 使用指定编码表创建转换流
    write('a') -> "GBK" -> 97 OutputStream out -> 文件     // 使用默认UTF-8 
    [AppleScript] 纯文本查看 复制代码 OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"));
    // 使用指定的GBK
    OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBK");
    o.write("你") -> GBK -> 7676 -> 文件
    写数据: 字符流 -------> 字节流 
5.2.5 InputStreamReader类介绍及使用 
    java.io.InputStreamReader类: 输入转换流. 字节流通往字符流的桥梁 
    // 构造方法 
   [AppleScript] 纯文本查看 复制代码  InputStreamReader(InputStream in): 使用默认编码表创建转换流
    InputStreamReader(InputStream in, String charsetName): 使用指定编码表创建转换流
    // 使用默认UTF-8
    InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"));
    // 使用指定的GBK
    InputStreamReader r = new InputStreamReader(new FileInputStream("a.txt"), "GBK");
    bbb int ch = r.read() <------GBK----------- 字节byte 989898
    r.read(chs)
    读数据: 字符流 <------ 字节流 
5.3 序列化流(对象流) 
5.3.1 序列化和反序列化概述 
    序列化: 内存中的对象转换为字节序列, 以流的方式写入到磁盘的文件中 
    对象转字节 
    反序列化: 磁盘文件中的字节序列, 以流的方式读取到内存中变成对象 
    字节转对象 
    通过序列化流, 我们可以将内存中的数据方便的存储到磁盘上, 下次程序启动后也能从磁盘读取恢复之前的对象状态 
    OutputStream 
    |_ ObjectOutputStream类: 对象字节输出流 
    InputStream 
    |_ ObjectInputStream类: 对象字节输入流 
5.3.2 对象序列化流: ObjectOutputStream 
    [AppleScript] 纯文本查看 复制代码 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.Serializable 接口) 
    如果某个属性不需要序列化, 则需要用 transient 修饰为瞬态的 
    如果要将集合序列化, 那么集合中存储的对象也必须是可序列化的 
5.3.4 对象反序列化流: ObjectInputStream 
    java.io.ObjectInputStream类: 对象字节输入流 
    // 构造方法 
    [AppleScript] 纯文本查看 复制代码 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(); 
5.3.5 transient瞬态关键字: 避免属性序列化 
    static 修饰的成员变量属于类不属于对象, 所以不能序列化 
    transient 修饰的成员变量, 不能被序列化 
    如果对象的某个属性不希望被序列化, 可以使用transient修饰, 这样就不会被对象流写到文件中 
5.3.6 InvalidClassException异常: 原因和解决方案 
    serialVersionUID序列号的作用: 
    序列化操作时, 会根据类生成一个默认的 serialVersionUID 属性, 写入到文件中. 
    该版本号是根据类中成员计算出来的一个数值. 当类的成员发生改变时, 序列版本号也会发生变化 
    当代码中的类和读取的对象序列版本号不一致时, 就会抛出InvalidClassException 
    为了避免这种问题, 我们可以手动写死这个序列号, 这样无论成员如何变化, 序列版本号都是一样的 
 
 
 
5.4 打印流 
5.4.1 打印流PrintStream: 概述和使用 
    PrintStream特点: 
    1. 只有输出流, 没有输入流 
    2. PrintStream永远不会抛出IOException 
    3. 有特殊方法 print(), println(), 可以输出任意类型的值 
    java.io.PrintStream类: 字节打印流 
    // 构造方法 
    [AppleScript] 纯文本查看 复制代码 PrintStream(File file): 创建字节打印流, 输出到一个文件
    PrintStream(OutputStream out): 创建字节打印流, 输出到一个字节输出流
    PrintStream(String fileName): 创建字节打印流, 输出到一个文件路径     注意事项: 
    如果用 write() 方法, 会查编码表 
    如果用 print(), println(), 则原样输出 
    java.lang.System类: 
    // 静态方法 
    static void setOut(PrintStream out): 设置System.out的输出目的地为参数的打印流 
六、IO框架体系结构 
    // 体系结构: 
    字节流 
    [AppleScript] 纯文本查看 复制代码 |_ InputStream # 字节输入流
    | |_ FileInputStream # 专门操作文件的字节输入流
    | |_ BufferedInputStream # 带有缓冲区的字节输入流, 效率高
    | |_ ObjectInputStream # 对象输入流
    |
    |_ OutputStream # 字节输出流
    |_ FileOutputStream # 专门操作文件的字节输出流
    |_ BufferedOutputStream # 带有缓冲区的字节输出流, 效率高
    |_ ObjectOutputStream # 对象输出流
    |_ PrintStream # 字节打印流     字符流 
   [AppleScript] 纯文本查看 复制代码  |_ Reader # 字符输入流
    | |_ BufferedReader # 带有缓冲区的字符输入流, 效率高
    | |_ InputStreamReader # 将字节流转换为字符流输入的转换输入流
    | |_ FileReader # 专门操作文件的字符输入流
    |
    |_ Writer # 字符输出流
    |_ BufferedWriter # 带有缓冲区的字符输出流, 效率高
    |_ OutputStreamWriter # 将字符流转换为字节流输出的转换输出流
    | |_ FileWriter # 专门操作文件的字符输出流 
 
 
 
 
 |   
        
 
    
    
    
     
 
 |