day11-字符流、属性集、缓冲流、转换流、序列化流笔记

学习目标

- 能够使用FileWriter写数据的5个方法
	- public void write(int c) :写出一个字符。
	- public void write(char[] cbuf) 写字符数组中的多个字符
	- public abstract void write(char[] b, int off, int len) 写字符数组的一部分
	- public void write(String str) :写出一个字符串。
	- void write(String str, int off, int len) 写入字符串的某一部分。
- 能够说出FileWriter中关闭和刷新方法的区别
	- flush :刷新缓冲区,把内存缓冲区中的数据刷新到文件中,刷新完后,流对象可以继续使用。
	- close :关闭流,释放系统资源。关闭前会刷新缓冲区。流关闭之后就不能在使用了
- 能够使用FileWriter写数据实现换行和追加写
	1.续写(追加写):使用两个参数的构造方法
		FileWriter(File file, boolean append)
		FileWriter(String fileName, boolean append)
	2.换行:使用换行符号
		windows:\r\n
		linux: \n
		mac: \r  从Mac OS X开始与linux统一		
- 能够使用FileReader读数据一次一个字符
	//1.创建FileReader对象,构造方法中绑定要读取的数据源
	FileReader fr = new FileReader("day15\\c.txt");
	//2.使用FileReader对象中的方法read,以字符的方式读取文件
	//public int read() 一次读取一个字符并返回
	int len = 0;
	while ((len = fr.read())!=-1){
		System.out.print((char)len);
	}
	//3.释放资源
	fr.close();
- 能够使用FileReader读数据一次一个字符数组
	//1.创建FileReader对象,构造方法中绑定要读取的数据源
	FileReader fr = new FileReader("day15\\c.txt");
	//2.使用FileReader对象中的方法read,以字符的方式读取文件
	//public int read() 一次读取一个字符并返回
	char[] chars = new char[1024];
	int len = 0;
	while ((len =fr.read(chars))!=-1){
		System.out.println(new String(chars,0,len));
	}
	//3.释放资源
	fr.close();
- 能够使用Properties的load方法加载文件中配置信息(必须会)
	//1.创建Properties集合对象
	Properties prop = new Properties();
	//2.使用Properties集合对象中的方法load,把硬盘中保存键值对的文件,读取到内存中使用
	//prop.load(new FileInputStream("day21\\prop.properties"));
	prop.load(new FileReader("day21\\prop.properties"));
	//3.遍历Properties集合
	Set<String> set = prop.stringPropertyNames();
	for (String key : set) {
		String value = prop.getProperty(key);
		System.out.println(key+"\t"+value);
	}
- 能够使用字节缓冲流读取数据到程序(必须会)
	1.创建BufferedInputStream对象,构造方法中传递FileInputStream对象
	2.使用BufferedInputStream对象中的方法read,以字节的方式读取文件
	3.释放资源
- 能够使用字节缓冲流写出数据到文件(必须会)
	1.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象
	2.使用BufferedOutputStream对象中的方法write,把数据以字节的方式写入到内存缓冲区中
	3.使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据刷新到文件中
	4.释放资源
- 能够明确字符缓冲流的作用和基本用法(必须会)
	1.创建BufferedReader对象,构造方法中传递FileReader对象
	2.使用BufferedReader对象中的方法read|readLine,以字符的方式读取文件
	3.释放资源
	
	1.创建BufferedWriter对象,构造方法中传递FileWriter对象
	2.使用BufferedWriter对象中的方法write,把数据写到内存缓冲区中
	3.使用BufferedWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
	4.释放资源(会先调用flush方法刷新数据)
- 能够使用缓冲流的特殊功能(必须会)
	BufferedReader:String readLine() 读取一个文本行。
	BufferedWriter:void newLine() 写入一个行分隔符。写换行,会根据系统的不同写不同的换行符号
- 能够阐述编码表的意义(记住)
	//编码表就是一个生活中文字和计算机存储字节的一个对应关系表
	ASCII: 0:48  A:65 a:97
	GBK:中文码表,一个中文占用2个字节
	UTF-8:万国表,一个中文占用3个字节
	编码:字符转换为字节(生活中的文字==>计算机存储的)
	解码:字节转换为字符(计算机存储==>生活中的)
- 能够使用转换流读取指定编码的文本文件(必须会)
	1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和指定的编码表名称
	2.使用InputStreamReader对象中的方法read,以字符的形式读取文件
	3.释放资源
- 能够使用转换流写入指定编码的文本文件(必须会)
	1.创建OutputStreamWriter对象,构造方法中传递FileOutputStream对象和指定的编码表名称
	2.使用OutputStreamWriter对象中方法write,把数据写入到内存缓冲区中
	3.使用OutputStreamWriter对象中方法flush,把内存缓冲区中的数据刷新到文件中
	4.释放资源(会先调用flush方法刷新数据)
- 能够使用序列化流写出对象到文件(必须会)
	1.创建ObjectOutputStream对象,构造方法中传递FileOutputStream对象
	2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中保存
	3.释放资源
- 能够使用反序列化流读取文件到程序中(必须会)
	1.创建ObjectInputStream对象,构造方法中传递FileInputStream对象
	2.使用ObjectInputStream对象中方法readObject,读取文件中保存的对象
	3.释放资源

第一章 字符流

1.使用字节输入流读取含有中文的文件

package com.itheima.demo01Reader;

import java.io.FileInputStream;
import java.io.IOException;

/*
    使用字节输入流读取含有中文的文件
        UTF-8编码:一个中文占用3个字节
        GBK编码:一个中文占用2个字节
 */
public class Demo01FileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day11\\1.txt");
        int len = 0;
        while ((len = fis.read())!=-1){
            System.out.print((char)len);//ä½ å¥½ 一次读取一个字节,把一个字节(中文1/3)查询编码表转换为字符,出现乱码
        }
        fis.close();
    }
}

2.字符输入流介绍

java.io.Reader:字符输入流
	用于读取字符流的抽象类。
	是所有字符输入流最顶层的父类,里边定义了所有字符输入流共性的成员方法,所有的字符输入流都可以使用
共性的成员方法:
	int read() 读取单个字符。
	int read(char[] cbuf) 将字符读入数组。
	void close() 关闭该流并释放与之关联的所有资源。
java.io.FileReader:文件字符输入流 extends InputStreamReader(转换流) extends Reader
作用:
	把文件中的数据以字符的方式读取到内存中
构造方法:
	FileReader(String fileName)
	FileReader(File file) 
	参数:传递要读取的数据源
	   String fileName:数据源就是一个文件路径
	   File file:数据源就是一个文件 

3.使用字符输入流读取文件的步骤(重点)

package com.itheima.demo01Reader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/*
    使用字符输入流读取文件的步骤(重点)
    1.创建字符输入流FileReader对象,构造方法中绑定要读取的数据源
    2.使用FileReader对象中的方法read,以字符的方式读取文件
    3.释放资源
    String类的构造方法:
        String(char[] value) 可以把字符数组转换为字符串
        String(char[] value, int offset, int count) 把字符数组的一部分转换为字符串
            int offset:数组开始索引   int count:转换个数
 */
public class Demo02FileReader {
    public static void main(String[] args) throws IOException {
        //1.创建字符输入流FileReader对象,构造方法中绑定要读取的数据源
        FileReader fr = new FileReader("day11\\1.txt");
        //2.使用FileReader对象中的方法read,以字符的方式读取文件
        //int read() 读取单个字符。
        /*int len = 0;
        while ((len=fr.read())!=-1){
            System.out.print((char)len);
        }*/

        //int read(char[] cbuf) 使用字符数组一次读取多个字符
        char[] chars = new char[1024];
        int len = 0;
        while ((len=fr.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }

        //3.释放资源
        fr.close();
    }
}

4.字符输出流介绍

java.io.Writer:字符输出流
	写入字符流的抽象类。
	是所有字符输出流最顶层的父类,里边定义了所有字符输出流中共性的成员方法,所有字符输出流都可以使用
共性的成员方法:
	public abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。
	public abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。
	public void write(int c) :写出一个字符。
	public void write(char[] cbuf) :将 b.length字符从指定的字符数组写出此输出流。
	public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
	public void write(String str) :写出一个字符串
	public void write(String str, int off, int len) 写入字符串的某一部分。
java.io.FileWriter:文件字符输出流 extends OutputStreamWriter(转换流)  extends Writer
作用:
	把内存中的数据,以字符的方式写入到文件中
构造方法:
	FileWriter(File file)
	FileWriter(String fileName)
	参数:传递写入的目的地
		 String fileName:目的地是一个文件的路径
		 File file:目的地是一个文件
	一个参数构造方法的作用:
		1.会创建FileWriter对象
		2.会根据构造方法中传递的文件|文件的路径,创建一个新的空白的文件
		3.会把FileWriter对象,执向空白的文件

5.使用字符输出流基本步骤(重点)

package com.itheima.demo02Writer;

import java.io.FileWriter;
import java.io.IOException;

/*
    使用字符输出流基本步骤(重点)
    1.创建字符输出流FileWriter对象,构造方法中邦定要写入的目的地
    2.使用FileWriter对象中的方法write,把数据写入到[内存缓冲区]中
    3.使用FileWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
    4.释放资源(在释放资源前,自动的调用flush方法把数据刷新到文件中)
 */
public class Demo01FileWriter {
    public static void main(String[] args) throws IOException {
        //1.创建字符输出流FileWriter对象,构造方法中邦定要写入的目的地
        FileWriter fw = new FileWriter("day11\\2.txt");
        //2.使用FileWriter对象中的方法write,把数据写入到[内存缓冲区]中
        //void write(int c)  一次写一个字符
        fw.write(97);
        //3.使用FileWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        //fw.flush();
        //4.释放资源(在释放资源前,自动的调用flush方法把数据刷新到文件中)
        fw.close();
    }
}

6.关闭和刷新的区别(面试)

  • flush:把内存缓冲区中的数据刷新到文件中,刷新完之后,流对象可以继续使用
  • close:释放资源,在释放资源之前,把内存缓冲区中的数据刷新到文件中
    刷新完之后,流对象就已经关闭了,就不能在使用了
package com.itheima.demo02Writer;

import java.io.FileWriter;
import java.io.IOException;

/*
    关闭和刷新的区别(面试)
    - flush:把内存缓冲区中的数据刷新到文件中,刷新完之后,流对象可以继续使用
    - close:释放资源,在释放资源之前,把内存缓冲区中的数据刷新到文件中
        刷新完之后,流对象就已经关闭了,就不能在使用了
    问题:
        1.3.txt文件中会有数据吗?  有
          数据是什么: 中国
        2.程序的运行会出现问题吗?  会出现异常
 */
public class Demo02closeAndflush {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("day11\\3.txt");
        fw.write('中');
        fw.flush();
        fw.write('国');
        fw.close();
        //fw.write('人');//IOException: Stream closed 流已经关闭了,就不能在使用了
    }
}

7.字符输出流写数据的其他方法(重点)

package com.itheima.demo02Writer;

import java.io.FileWriter;
import java.io.IOException;

/*
    字符输出流写数据的其他方法(重点)
     void write(int c) 写入单个字符。
     void write(char[] cbuf) 写入字符数组。
     abstract  void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
     void write(String str) 写入字符串。
     void write(String str, int off, int len) 写入字符串的某一部分。
 */
public class Demo03FileWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("day11\\4.txt");
        //void write(int c) 写入单个字符。
        fw.write('@');//@

        //void write(char[] cbuf) 写入字符数组。
        char[] chars = {'你','好','a','b','1','2','#'};
        fw.write(chars);//你好ab12#

        //abstract  void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
        fw.write(chars,2,2);//ab

        //void write(String str) 写入字符串。
        fw.write("你若安好,便是晴天");//你若安好,便是晴天

        //void write(String str, int off, int len) 写入字符串的某一部分。
        fw.write("你若安好,便是晴天",5,4);//便是晴天

        fw.close();
    }
}

8.字符输出流的续写和换行(重点)

字符输出流的续写和换行(重点):和字节流一样
1.续写(追加写):使用两个参数的构造方法
	FileWriter(String fileName, boolean append)
	FileWriter(File file, boolean append)
	参数:
		File file|String fileName:写入数据的目的地
		boolean append:续写的开关
			true:可以续写,使用构造方法创建对象,文件名相同,不会创建新的文件覆盖之前同名的文件,会继续往文件的末尾写数据
			false:不可以续写,使用构造方法创建对象,文件名相同,会创建一个新的空白文件覆盖之前同名的文件,在新的文件中写数据
2.换行:使用换行符号
	Windows系统里,每行结尾是 回车+换行 ,即 \r\n
	linux,Unix系统里,每行结尾只有 换行 ,即 \n
	Mac系统里,每行结尾是 回车 ,即 \r 。从 Mac OS X开始与Linux统一。
package com.itheima.demo02Writer;

import java.io.FileWriter;
import java.io.IOException;

/*
    字符输出流的续写和换行(重点)
    和字节流一模一样
    续写:使用两个参数的构造方法
        FileWriter(File file, boolean append)
        FileWriter(String fileName, boolean append)
        参数:
            File file,String fileName:写的目的地
            boolean append:续写开关 true:可以续写 false:不可以
    换行:使用换行符号 \r\n(windows)
 */
public class Demo04FileWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("day11\\5.txt",true);
        for (int i = 1; i <= 10; i++) {
            fw.write("你好"+i+"\r\n");
        }
        fw.close();
    }
}

字符流和字节流的区别

1.字节流读取的和写入都是字节;字符流读取的和写入的都是字符

2.所有的数据(文本,音乐,视频,图片…),都是以字节的方式存储的,使用字节流可以读写任意的文件

3.使用字节流读取的文件中包含中文,如果一次读取一个字节(1/2GBK,1/3UTF-8个中文),使用起来不方便,可能会出现乱码

4.使用字符流读取含有中文文本文件,一次读取一个字符(中文,英文,数字,符号…),使用起来很方便

什么时候使用字符流:读写文本文件(使用记事本打开能看懂)

什么时候使用字节流:读写非文本文件(图片,视频,音频…)

第二章 IO资源的处理(重点)

1.JDK7前异常处理

package com.itheima.demo03TryCatch;

import java.io.FileWriter;
import java.io.IOException;

/*
    在JDK1.7之前使用try...catch...finally处理流中的异常
    格式:
        try{
            可能出现异常的代码
        }catch(定义一个异常相关的变量){
            异常的处理逻辑
        }
        ...
        catch(定义一个异常相关的变量){
            异常的处理逻辑
        }
        finally{
            无论是否有异常,一定会执行的代码(释放资源)
        }
    快捷键:
        选中出现异常的代码;ctrl+alt+T==>选择 try...catch...finally
 */
public class Demo01JDK7Before {
    public static void main(String[] args) {
        /*
            1.把fw.close()放在finally,程序报错  Cannot resolve symbol 'fw' 找不到这个变量fw
                变量的作用域,在变量所在的大括号{ }范围内有效
                解决:
                    提高变量的作用域,把变量fw定义在try的外边
            2.Variable 'fw' might not have been initialized 变量fw没有被初始化
                 fw是一个局部变量,没有默认值,变量在定义的时候可以不用赋值,但是使用的时候必须有值
                 fw = new FileWriter("day11\\5.txt",true); 这行代码报错了 fw有值吗?
                 解决:
                    给变量fw赋一个默认值 FileWriter fw = null;
         */
        FileWriter fw = null;
        try {
            //可能出现异常的代码
            fw = new FileWriter("e:\\day11\\5.txt",true);
            for (int i = 1; i <= 10; i++) {
                fw.write("你好"+i+"\r\n");
            }

        } catch (IOException e) {
            //异常的处理逻辑
            e.printStackTrace();
        } finally {
            //无论是否有异常,一定会执行的代码(释放资源)
            /*
                3.fw.close();  Unhandled exception: java.io.IOException close方法本身声明抛出了异常
                    解决:
                        把fw.close()在放在try中
                4.如果fw = new FileWriter("e:\\day11\\5.txt",true);这行代码创建对象失败了
                    fw的默认值就是null,而null是不能调用方法的,会抛出空指针异常
                    解决:
                        增加一个非空判断
             */
            if(fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("后续100行代码!");
    }
}

2.JDK7后异常处理

package com.itheima.demo03TryCatch;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

/*
     在JDK1.7之后使用try...catch.处理流中的异常
     在JDK1.7版本开始,在try关键字的后边,可以写一个小括号()
     在小括号()中可以定义流对象,这样这个流对象的作用域就在try中有效
     使用完毕流对象,会自动释放资源,省略finally
     try(定义流对象){
            可能出现异常的代码
        }catch(定义一个异常相关的变量){
            异常的处理逻辑
        }
        ...
        catch(定义一个异常相关的变量){
            异常的处理逻辑
        }
     注意:
        不是所有的对象,都可以放在try后边的小括号中
        必须使用了AutoCloseable的类才可以自动释放资源
 */
public class Demo02JDK7Ater {
    public static void main(String[] args) {
        try(FileWriter fw = new FileWriter("day11\\5.txt",true);) {
            for (int i = 1; i <= 10; i++) {
                fw.write("你好"+i+"\r\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        try( FileInputStream fis = new FileInputStream("c:\\1.jpg");
             FileOutputStream fos = new FileOutputStream("d:\\1.jpg");) {
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len=fis.read(bytes))!=-1){
                fos.write(bytes,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        /*try(Person p = new Person();) {
        } catch (Exception e) {
            e.printStackTrace();
        }*/

    }
}

第三章 Properties集合

1.Properties集合的基本使用

package com.itheima.demo04Properties;

import java.util.Properties;
import java.util.Set;

/*
    java.uitl.Properties extends Hashtable<k,v> implements Map<k,v>
    1.Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
        Properties集合是一个和IO流相结合的集合
        我们可以使用Properties集合中的方法store,把集合中的临时数据,持久化存储到硬盘的文件中(内存==>硬盘)
        我们可以使用Properties集合中的方法load,把硬盘文件中存储的数据(键值对),读取到集合中使用(硬盘==>内存)
    2.属性列表中每个键及其对应值都是一个字符串
        Properties集合是一个双列集合,键和值的泛型默认都是String类型
 */
public class Demo01Properties {
    public static void main(String[] args) {
        /*
            Properties集合的基本使用:1.会使用集合存储数据 2.会遍历集合取出集合中数据 3.知道每种集合的特性
            Properties集合健和值默认都是String类型,在集合中有很多很String相关的特有方法
            1.Object setProperty(String key, String value) 往Properties集合中添加键值对,相当于Map集合中的put方法
            2.String getProperty(String key) 根据key获取value值,相当于Map集合中的get方法
            3.Set<String> stringPropertyNames() 返回此属性列表中的键集,相当于Map集合中的keySet方法
         */
        //创建Properties集合对象
        Properties prop = new Properties();
        //使用setProperty方法往Properties集合中添加键值对
        prop.setProperty("迪丽热巴","18");
        prop.setProperty("古力娜扎","19");
        prop.setProperty("马尔扎哈","28");
        prop.setProperty("佟丽娅","18");
        //使用stringPropertyNames方法,取出Properties集合中所有的key,存储到一个Set集合中
        Set<String> set = prop.stringPropertyNames();
        //遍历Set集合,获取Properties集合中每一个key
        for (String key : set) {
            //使用getProperty方法,根据key获取value值
            String value = prop.getProperty(key);
            System.out.println(key+"="+value);
        }
    }
}

2.Properties集合中的方法store(了解-扩展)

package com.itheima.demo04Properties;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

/*
    Properties集合中的方法store(了解-扩展)
    我们可以使用Properties集合中的方法store,把集合中的临时数据,持久化存储到硬盘的文件中(内存==>硬盘)
    void store(OutputStream out, String comments)
    void store(Writer writer, String comments)
    参数:
        OutputStream out:传递字节输出流,不能写中文
        Writer writer:传递字符输出流,可以写中文
        String comments:注释,解释说明保存文件是干什么用的,不能写中文,默认使用Unicode编码,写中文会出现乱码
    使用步骤:
        1.创建Properties集合对象,往集合中添加数据
        2.使用Properties集合中的方法store,把集合中的临时数据,持久化存储到硬盘的文件中
 */
public class Demo02store {
    public static void main(String[] args) throws IOException {
        //1.创建Properties集合对象,往集合中添加数据
        Properties prop = new Properties();
        prop.setProperty("迪丽热巴","18");
        prop.setProperty("古力娜扎","19");
        prop.setProperty("马尔扎哈","28");
        prop.setProperty("佟丽娅","18");
        //2.使用Properties集合中的方法store,把集合中的临时数据,持久化存储到硬盘的文件中
        /*FileOutputStream fos = new FileOutputStream("day11\\prop1.txt");
        prop.store(fos,"save data");
        fos.close();*/

        //在工作中,对象只使用一次,可以使用匿名对象,使用完毕会自动释放资源
        prop.store(new FileOutputStream("day11\\prop1.txt"),"save data");
        prop.store(new FileWriter("day11\\prop2.txt"),"");
        //在工作中,存储键值对的文件一般都使用.properties结尾
        prop.store(new FileWriter("day11\\prop.properties"),"");
    }
}

3.Properties集合中的方法load(重点)

package com.itheima.demo04Properties;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/*
    Properties集合中的方法load(重点)
    我们可以使用Properties集合中的方法load,把硬盘文件中存储的数据(键值对),读取到集合中使用(硬盘==>内存)
    void load(InputStream inStream) 传递字节输入流,不能读取中文
    void load(Reader reader) 传递字符输入流,可以读取中文
    使用步骤:
        1.创建Properties集合对象
        2.使用Properties集合中的方法load,把硬盘文件中存储的数据(键值对),读取到集合中使用
        3.打印集合,查看结果
    注意:
        1.在存储键值对的文件中,使用#添加注释,被注释的内容不会被读取
        2.在存储键值对的文件中,使用=或者空格等一些符号,把键与值分割开
        3.在存储键值对的文件中,键与值默认都是String类型,不需要添加引号,会画蛇添足
 */
public class Demo03load {
    public static void main(String[] args) throws IOException {
        //1.创建Properties集合对象
        Properties prop = new Properties();
        //2.使用Properties集合中的方法load,把硬盘文件中存储的数据(键值对),读取到集合中使用
        //prop.load(new FileInputStream("day11\\prop.properties"));
        prop.load(new FileReader("day11\\prop.properties"));
        //3.打印集合,查看结果
        System.out.println(prop);
    }
}

prop.properties

#
#Sun Sep 26 10:27:01 CST 2021
#马尔扎哈=28
古力娜扎=19
迪丽热巴18
佟丽娅 18
"肖战"=20

第四章 缓冲流

1.概述

在这里插入图片描述

2.BufferedInputStream:字节缓冲输入流(重点)

/*
    java.util.BufferedInputStream:字节缓冲输入流 extends InputStream:字节输入流
    BufferedInputStream可以使用继承自InputStream的共性方法
       int read() 一次读取一个字节
       int read(byte[] b)  一次读取多个字节
       void close() 关闭此输入流并释放与该流关联的所有系统资源。
    BufferedInputStream的构造方法:
        BufferedInputStream(InputStream in) 带默认缓冲区大小的BufferedInputStream对象
        BufferedInputStream(InputStream in, int size)  带指定缓冲区大小的BufferedInputStream对象
        参数:
            InputStream in:传递字节输入流,可以传递InputStream的任意的子类对象
                传递FileInputStream,缓冲流就会给FileInputStream增加一个缓冲区,提高FileInputStream读取文件的效率
            int size:指定的缓冲区大小,不写默认8kb
   -------------------------------
   使用步骤:
    1.创建BufferedInputStream对象,构造方法中传递FileInputStream对象
    2.使用BufferedInputStream对象中的方法read,以字节的方式读取文件
    3.释放资源
 */
package com.itheima.demo05BufferedStream;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
    BufferedInputStream:字节缓冲输入流(重点)
    使用步骤:
        1.创建BufferedInputStream对象,构造方法传递FileInputStream对象
        2.使用BufferedInputStream对象中的方法read,以字节的方式读取文件
        3.释放资源
 */
public class Demo01BufferedInputStream {
    public static void main(String[] args) throws IOException {
        //1.创建BufferedInputStream对象,构造方法传递FileInputStream对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day11\\a.txt"));
        //2.使用BufferedInputStream对象中的方法read,以字节的方式读取文件
        //int read() 一个读取一个字节
        /*int len = 0;
        while ((len=bis.read())!=-1){
            System.out.println((char)len);
        }*/

        //int read(byte[] b) 一次读取多个字节
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len=bis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }

        //3.释放资源
        bis.close();
    }
}

3.BufferedOutputStream:字节缓冲输出流(重点)

/*
    java.io.BufferedOutputStream:字节缓冲输出流 extends OutputStream:字节输出流
    继承自父类的共性成员方法:
        void write(int b)  一次写一个字节
        void write(byte[] b)  一次写数组中的所有字节
        void write(byte[] b, int off, int len)  一次写字节数组的一部分
        void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
        void close() 关闭此输出流并释放与此流有关的所有系统资源。
    BufferedOutputStream构造方法:
        BufferedOutputStream(OutputStream out) 创建一个具有默认缓冲区大小的BufferedOutputStream
        BufferedOutputStream(OutputStream out, int size) 创建一个具有指定缓冲区大小的BufferedOutputStream
        参数:
            OutputStream out:传递OutputStream字节输出流,可以传递OutputStream的任意的子类对象
                传递FileOutputStream对象,缓冲流就会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入的效率
            int size:指定缓冲区的大小(内部数组的长度),不写默认8kb
    --------------------------------------
    1.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象
    2.使用BufferedOutputStream对象中的方法write,把数据写入到内存缓冲区中
    3.使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据刷新到文件中
    4.释放资源(会先调用flush方法刷新数据)
 */
package com.itheima.demo05BufferedStream;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    BufferedOutputStream:字节缓冲输出流(重点)
    使用步骤:
        1.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象
        2.使用BufferedOutputStream对象中的方法write,把数据写入到[内存缓冲区]中
        3.使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        4.释放资源(在释放资源前,也会自动调用flush方法刷新数据)
 */
public class Demo02BufferedOutputStream {
    public static void main(String[] args) throws IOException {
        //1.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day11\\6.txt"));
        //2.使用BufferedOutputStream对象中的方法write,把数据写入到[内存缓冲区]中
        bos.write("你好".getBytes());
        //3.使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        bos.flush();
        //4.释放资源(在释放资源前,也会自动调用flush方法刷新数据)
        bos.close();
    }
}

4.复制文件测试缓冲流的效率

package com.itheima.demo05BufferedStream;

import java.io.*;

/*
    复制文件测试缓冲流的效率
 */
public class Demo03CopyFile {
    public static void main(String[] args) {
        long s = System.currentTimeMillis();
        //copyFile01();
        copyFile02();
        long e = System.currentTimeMillis();
        System.out.println("复制文件共耗时:"+(e-s)+"毫秒!");
    }

    /*
         使用BufferedInputStream和BufferedOutputStream一次读一个字节,写一个字节复制文件
        全球通史.txt  4.91 MB (5,155,785 字节)  复制文件共耗时:425毫秒!
     */
    private static void copyFile02() {
        try ( BufferedInputStream bis = new BufferedInputStream(new FileInputStream("c:\\全球通史.txt"));
              BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\全球通史.txt"));) {
            //一读一写复制文件
            int len = 0;
            while ((len=bis.read())!=-1){
                bos.write(len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
        使用FileInputStream和FileOutputStream一次读一个字节,写一个字节复制文件
        全球通史.txt  4.91 MB (5,155,785 字节) 复制文件共耗时:34838毫秒!
     */
    private static void copyFile01() {
        try (FileInputStream fis = new FileInputStream("c:\\全球通史.txt");
             FileOutputStream fos = new FileOutputStream("d:\\全球通史.txt");){
            //一读一写复制文件
            int len = 0;
            while ((len=fis.read())!=-1){
                fos.write(len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5.BufferedReader:字符缓冲输入流(重点)

/*
    java.io.BufferedReader:字符缓冲输入流 extends Reader:字符输入流
    有继承自父类的共性成员方法:
        int read() 读取单个字符。
        int read(char[] cbuf) 将字符读入数组。
        void close() 关闭该流并释放与之关联的所有资源。
     构造方法:
        BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
        BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。
        参数:
             Reader in:传递字符输入流,可以传递Reader的任意的子类对象
                传递FileReader,缓冲流就可以给FileReader增加一个缓冲区,提高FileReader读取文件的效率
             int sz:指定的缓冲区大小
     特有的成方法:
        String readLine() 读取一个文本行。
        通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行(\r\n)。
        返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
     使用步骤:
        1.创建BufferedReader对象,构造方法中传递FileReader对象
        2.使用BufferedReader对象中的方法read|readLine,以字符的方式读取文件
        3.释放资源
 */
package com.itheima.demo05BufferedStream;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/*
    BufferedReader:字符缓冲输入流(重点)
    使用步骤:
        1.创建BufferReader对象,构造方法中传递FileReader对象
        2.使用BufferReader对象中的方法read|readLine,以字符的方式读取文件
        3.释放资源
 */
public class Demo04BufferedReader {
    public static void main(String[] args) throws IOException {
        //1.创建BufferReader对象,构造方法中传递FileReader对象
        BufferedReader br = new BufferedReader(new FileReader("day11\\b.txt"));
        //2.使用BufferReader对象中的方法read|readLine,以字符的方式读取文件
        int len = 0;
        while ((len=br.read())!=-1){
            /*
                read方法会读取每行结尾的回车换行符号
                你好1(\r\n)
                你好2(\r\n)
                你好3
             */
            System.out.print((char)len);
        }
        //3.释放资源
        br.close();
    }
}
package com.itheima.demo05BufferedStream;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/*
    BufferedReader:字符缓冲输入流(重点)
    BufferedReader特有的方法readLine
        String readLine() 读取一个文本行。
        通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行(\r\n)。
        返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
 */
public class Demo05BufferedReader {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("day11\\b.txt"));

        /*
            我们发现使用readLine方法读取文件是一个重复的过程
            所以我们可以使用循环优化,不知道文件中有多少行内容,使用while循环
            while循环结束的条件,readLine方法返回null结束
         */
        String line;
        while ((line=br.readLine())!=null){
            /*
                readLine方法使用每行结尾的\r\n作为行结束的判断条件,但是不会读取给我们
                你好1你好2null你好3
                文件中的null不是默认null,是字符串"null"
             */
            System.out.print(line);
        }

        br.close();

        /*
            String line = br.readLine();
            System.out.println(line);//你好1

            line = br.readLine();
            System.out.println(line);//你好2

            line = br.readLine();
            System.out.println(line);//你好3

            line = br.readLine();
            System.out.println(line);//null
         */
    }
}

6.BufferedWriter:字符缓冲输出流(重点)

/*
    java.io.BufferedWriter:字符缓冲输出流 extends Writer:字符输出流
    有继承自父类的共性成员方法:
        public void write(int c) :写出一个字符。
        public void write(char[] cbuf) :把字符数组中所有的字符写出
        public void write(char[] b, int off, int len) :写字符数组的一部分数据 int off:开始索引 int len:写的个数
        public void write(String str) :写出一个字符串。
        public void write(String str, int off, int len);写字符串一部分数据 int off:开始索引 int len:写的个数
    构造方法:
        BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。
        BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
        参数:
             Writer out:传递字符输出流,可以传递Writer的任意的子类对象
                传递FileWriter,缓冲流就会给FileWriter增加一个缓冲区,提高FileWriter写入数据的效率
             int sz:指定的缓冲区大小
   特有的成员方法:
        void newLine() 写入一个行分隔符。写换行,会根据系统不同,而写不同的换行符号
        Windows系统里,每行结尾是 回车+换行 ,即 \r\n
        linux,Unix系统里,每行结尾只有 换行 ,即 \n
        Mac系统里,每行结尾是 回车 ,即 \r 。从 Mac OS X开始与Linux统一。
   使用步骤:
    1.创建BufferedWriter对象,构造方法中传递FileWriter
    2.使用BufferedWriter对象中的方法write,把数据写入到内存缓冲区中
    3.使用BufferedWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
    4.释放资源(会先调用flush方法,刷新数据)
 */
package com.itheima.demo05BufferedStream;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/*
    BufferedWriter:字符缓冲输出流(重点)
    使用步骤:
        1.创建BufferedWriter对象,构造方法中传递FileWriter对象
        2.使用BufferedWriter对象中的方法write,把数据写入到内存缓冲区中
        3.使用BufferedWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        4.释放资源(先自动调用flush方法,把数据刷新到文件中)
 */
public class Demo06BufferedWriter {
    public static void main(String[] args) throws IOException {
        //1.创建BufferedWriter对象,构造方法中传递FileWriter对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\c.txt",true));
        //2.使用BufferedWriter对象中的方法write,把数据写入到内存缓冲区中
        for (int i = 1; i <=3 ; i++) {
            //bw.write("呵呵"+i+"\r\n");
            bw.write("呵呵"+i);
            bw.newLine();//写换行
        }
        //3.使用BufferedWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中
        bw.flush();
        //4.释放资源(先自动调用flush方法,把数据刷新到文件中)
        bw.close();
    }
}

7.练习:文本排序

package com.itheima.demo05BufferedStream;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

/*
    练习:文本排序
        把出师表按照1,2,3,4,...顺序排序
    分析:
        1.创建ArrayList集合对象,泛型使用String
        2.创建BufferedReader对象,构造方法中传递FileReader对象
        3.创建BufferedWriter对象,构造方法中传递FileWriter对象
        4.使用BufferedReader对象中的方法readLine,以行的方式读取文本
        5.把读取到的每行文本存储到ArrayList集合中
        6.使用Collections集合工具类中的方法sort,按照比较器产生的规则排序
        7.遍历集合,获取每一行文本
        8.使用BufferedWriter对象中的方法write,把遍历得到的每行文本写入到内存缓冲区中
        9.使用BufferedWriter对象中的方法newLine,每写一行文本,写一个换行
        10.释放资源
 */
public class Demo07Test {
    public static void main(String[] args) throws IOException {
        //1.创建ArrayList集合对象,泛型使用String
        ArrayList<String> list = new ArrayList<>();
        //2.创建BufferedReader对象,构造方法中传递FileReader对象
        BufferedReader br = new BufferedReader(new FileReader("day11\\csblx.txt"));
        //3.创建BufferedWriter对象,构造方法中传递FileWriter对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\csbzx.txt"));
        //4.使用BufferedReader对象中的方法readLine,以行的方式读取文本
        String line;
        while ((line=br.readLine())!=null){
            //5.把读取到的每行文本存储到ArrayList集合中
            list.add(line);
        }
        //6.使用Collections集合工具类中的方法sort,按照比较器产生的规则排序
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //按照每行的首字母升序排序
                //return o1.charAt(0)-o2.charAt(0);
                //按照每行.前边的数字升序排序
                return Integer.parseInt(o1.split("\\.")[0])-Integer.parseInt(o2.split("\\.")[0]);
            }
        });
        //7.遍历集合,获取每一行文本
        for (String s : list) {
            //8.使用BufferedWriter对象中的方法write,把遍历得到的每行文本写入到内存缓冲区中
            bw.write(s);
            //9.使用BufferedWriter对象中的方法newLine,每写一行文本,写一个换行
            bw.newLine();
        }
        //10.释放资源
        bw.close();
        br.close();
    }
}

要排序的文本:

3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无 大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之 慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉 以咨之,必能使行阵和睦,优劣得所。
2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明 之理,不宜偏私,使内外异法也。
1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士 忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲 薄,引喻失义,以塞忠谏之路也。
9.今当远离,临表涕零,不知所言。
6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之 中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十 有一年矣。
7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深 入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣 所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未 尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可 计日而待也。

第五章 转换流

1.编码表

就是生活中的文字和计算机中文字的对应关系表

a–>97–>01100001==>存储到计算机中

中–>20013–>‭0010000000001011‬==>存储到计算机中

编码:把能看懂的文字,转换为看不懂的文字(字符==>字节)

解码:把看不懂的文字,转换为能看懂的文字(字节==>字符)

常用的编码表:

ASCII字符集 (美国信息交换标准代码):英文,数字,标点符号和计算机中文字的对应关系

​ ‘0’–>48 ‘A’–>65 ‘a’–>97

ISO-8859-1字符集:拉丁码表

  • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
  • ISO-8859-1使用单字节编码,兼容ASCII编码。不支持中文

GBxxx字符集:国标

  • GB就是国标的意思,是为了显示中文而设计的一套字符集。兼容ASCII表
  • GB2312:简体中文码表。 7000多个简体汉字
  • GBK:目前操作系统默认中文码表(简体,繁体),存储一个中文使用2个字节,21003个汉字
  • GB18030:最新的中文码表。包含的文字最全(简体,繁体,少数民族,日韩文字)

Unicode字符集 :万国码

  • UTF-8:最常用的万国表,兼容所有国家的文字

  • 编码规则:

    • 128个US-ASCII字符,只需一个字节编码。
    • 拉丁文等字符,需要二个字节编码。
    • 大部分常用字(含中文),使用三个字节编码。
    • 其他极少使用的Unicode辅助字符,使用四字节编码。

2. 编码引出的问题

使用FileReader读取GBK编码的文件:会出现乱码,编码和解码不一致导致

package com.itheima.demo06ReverseStream;

import java.io.FileReader;
import java.io.IOException;

/*
    使用FileReader读取GBK编码的文件:会出现乱码,编码和解码不一致导致
    GBK编码:一个中文占用2个字节
    UTF-8编码:一个中文占用3个字节
 */
public class Demo01FileReader {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("day11\\GBK.txt");
        int len = 0;
        while ((len=fr.read())!=-1){
            System.out.print((char)len);//���
        }
        fr.close();
    }
}

3.转换流的原理(扩展)

在这里插入图片描述

4.InputStreamReader:字符转换输入流(重点)

/*
    java.io.InputStreamReader:字符转换输入流 extends Reader:字符输入流
    作用:
        InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
        解码:字节==>字符
    有继承自父类的共性成员方法:
        int read() 读取单个字符。
        int read(char[] cbuf) 将字符读入数组。
        void close() 关闭该流并释放与之关联的所有资源。
    构造方法:
        InputStreamReader(InputStream in)创建一个使用默认字符集的 InputStreamReader。
        InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader。
        参数:
             InputStream in:传递字节输入流,可以传递InputStream的任意的子类对象
             String charsetName:传递编码表名称,不区分大小写,可以传递GBK|gbk,UTF-8|utf-8...
                不写编码表名称,在IDEA中默认使用UTF-8编码
    ----------------------------------------------------------------------------------------------
    1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和指定的编码表名称
    2.使用InputStreamReader对象中的方法read,读取文件
    3.释放资源
    注意:
        指定的编码表名称和要读取的文件的编码必须一致,否则会出现乱码
 */
package com.itheima.demo06ReverseStream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

/*
    InputStreamReader:字符转换输入流(重点)
    InputStreamReader作用:
        是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
        编码 字节==>字符
    使用步骤:
        1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和指定的编码表名称
        2.使用InputStreamReader对象中的方法read,以指定的编码读取文件
        3.释放资源
    注意:
        指定的编码表名称和文件的编码必须一致,否则出现乱码
 */
public class Demo02InputStreamReader {
    public static void main(String[] args) throws IOException {
        //read_GBK();
        read_UTF8();
    }

    /*
        使用InputStreamReader读取UTF-8编码的文件
     */
    private static void read_UTF8() throws IOException {
        //1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和指定的编码表名称
        //InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\utf8.txt"),"GBK");//浣犲ソa1
        //InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\utf8.txt"),"UTF-8");//你好a1
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\utf8.txt"));//你好a1 不写编码表名称默认UTF-8(IDEA)
        //2.使用InputStreamReader对象中的方法read,以指定的编码读取文件
        int len = 0;
        while ((len=isr.read())!=-1){
            System.out.print((char)len);
        }
        //3.释放资源
        isr.close();
    }

    /*
        使用InputStreamReader读取GBk编码的文件
     */
    private static void read_GBK() throws IOException {
        //1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和指定的编码表名称
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\GBK.txt"),"GBK");
        //2.使用InputStreamReader对象中的方法read,以指定的编码读取文件
        int len = 0;
        while ((len=isr.read())!=-1){
            System.out.print((char)len);
        }
        //3.释放资源
        isr.close();
    }
}

5.OutputStreamWriter:字符转换输出流(重点)

/*
    java.io.OutputStreamWriter:字符转换输出流 extends Writer:字符输出流
    作用:
        OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
        编码:字符==>字节
    继承自父类的共性成员方法:
        public abstract void close() :关闭此输出流并释放与此流相关联的任何系统资源。
        public abstract void flush() :刷新此输出流并强制任何缓冲的输出字符被写出。
        public void write(int c) :写出一个字符。
        public void write(char[] cbuf) :将 b.length字符从指定的字符数组写出此输出流。
        public abstract void write(char[] b, int off, int len) :从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。
        public void write(String str) :写出一个字符串
        public void write(String str, int off, int len) 写入字符串的某一部分。
    构造方法:
        OutputStreamWriter(OutputStream out)创建使用默认字符编码的 OutputStreamWriter。
        OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter。
        参数:
            OutputStream out:传递字节输出流,可以传递OutputStream的任意的子类对象
            String charsetName:传递编码表名称,不区分大小写,可以传递GBK|gbk,UTF-8|utf-8...
                不写编码表名称,在IDEA中默认使用UTF-8编码
   ----------------------------------------------------------------------------
   使用步骤:
    1.创建OutputStreamWriter对象,构造方法中传递FileOutputStream对象和指定的编码表名称
    2.使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(编码:字符==>字节)
    3.使用OutputStreamWriter对象中方法flush,把内存缓冲区中的数据刷新到文件中(FileOutputStream写字节)
    4.释放资源(会先调用flush方法刷新数据)
 */
package com.itheima.demo06ReverseStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

/*
    OutputStreamWriter:字符转换输出流(重点)
    作用:
        OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节
        编码:字符==>字节
    使用步骤:
        1.创建OutputStreamWriter对象,构造方法传递FileOutputStream对象和指定的编码表名称
        2.使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(编码:字符==>字节)
        3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中(使用字节输出流写字节到文件中)
        4.释放资源
 */
public class Demo03OutputStreamWriter {
    public static void main(String[] args) throws IOException {
        //write_GBK();
        write_UTF8();
    }

    /*
        使用OutputStreamWriter写UTF-8编码的文件
     */
    private static void write_UTF8() throws IOException {
        //1.创建OutputStreamWriter对象,构造方法传递FileOutputStream对象和指定的编码表名称
        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\utf82.txt"),"utf-8");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\utf83.txt"));//不写编码表名称,默认UTF-8
        //2.使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(编码:字符==>字节)
        osw.write("你好");
        //3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中(使用字节输出流写字节到文件中)
        osw.flush();
        //4.释放资源
        osw.close();
    }

    /*
        使用OutputStreamWriter写GBK编码的文件
     */
    private static void write_GBK() throws IOException {
        //1.创建OutputStreamWriter对象,构造方法传递FileOutputStream对象和指定的编码表名称
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\gbk2.txt"),"gbk");
        //2.使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(编码:字符==>字节)
        osw.write("你好");
        //3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中(使用字节输出流写字节到文件中)
        osw.flush();
        //4.释放资源
        osw.close();
    }
}

6.练习:转换文件编码

将GBK编码的文本文件,转换为UTF-8编码的文本文件。

package com.itheima.demo06ReverseStream;

import java.io.*;

/*
    练习:转换文件编码
        将GBK编码的文本文件,转换为UTF-8编码的文本文件。
    分析:
       1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和GBk编码表名称
       2.创建OutputStreamWriter对象,构造方法中传递FileOutputStrea对象和UTF-8编码表名称
       3.使用InputStreamReader对象中的方法read,以GBK编码读取文件 4个字节==>(你好)
       4.使用OutputStreamWriter对象中的方法write,把读取到字符以UTF-8编码写入到内存缓冲区中(你好==>6个字节)
       5.释放资源
 */
public class Demo04Test {
    public static void main(String[] args) throws IOException {
        //1.创建InputStreamReader对象,构造方法中传递FileInputStream对象和GBk编码表名称
        InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\GBK.txt"),"GBK");
        //2.创建OutputStreamWriter对象,构造方法中传递FileOutputStrea对象和UTF-8编码表名称
        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\utf84.txt"),"UTF-8");
        //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\utf84.txt"));//不写编码表名称默认UTF-8
        FileWriter osw = new FileWriter("day11\\utf85.txt");
        //3.使用InputStreamReader对象中的方法read,以GBK编码读取文件 4个字节==>(你好)
        int len = 0;
        while ((len=isr.read())!=-1){//len=你好
            //4.使用OutputStreamWriter对象中的方法write,把读取到字符以UTF-8编码写入到内存缓冲区中(你好==>6个字节)
            osw.write(len);
        }
        //5.释放资源
        osw.close();
        isr.close();
    }
}

总结:

什么时候使用FileReader和FileWriter(读写字符的便捷类):读写的文件都是IDEA默认编码utf-8的文件
什么时候使用InputStreamReader和OutputStreamWriter:读写的文件不是IDEA默认编码utf-8的文件

第六章 序列化流

1.序列化流和反序列流的概述

在这里插入图片描述

2.ObjectOutputStream:对象的序列化流(重点)

package com.itheima.demo07SerializableStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/*
    java.util.ObjectOutputStream:对象的序列化流 extends OutputStream:字节输出流
    作用:把对象以流的方式写入到文件中
    构造方法:
        ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。
        参数:
            OutputStream out:字节输出流,可以传递OutputStream的任意的子类对象
    特有的成员方法:
        void writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。
    使用步骤(重点):
        1.创建ObjectOutputStream对象,构造方法中传递FileOutputStream对象
        2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
        3.释放资源
 */
public class Demo01ObjectOutputStream {
    public static void main(String[] args) throws IOException {
        //1.创建ObjectOutputStream对象,构造方法中传递FileOutputStream对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\person.txt"));
        //2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中
        oos.writeObject(new Person("小美女",18));
        //3.释放资源
        oos.close();
    }
}

package com.itheima.demo07SerializableStream;

import java.io.Serializable;

/*
    NotSerializableException:在进行序列化的时候程序抛出了,没有序列化异常
    类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
    Serializable接口是一个标记型接口,类(Person)实现了Serializable接口,接口就会给类添加一个标记(序列号)
    当我们进行序列化和反序列化的时候,会检查类上是否有这个标记
        有,进行序列化和反序列化成功
        没有,会抛出NotSerializableException异常
 */
public class Person implements Serializable{
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

3.ObjectInputStream:对象的反序列化流(重点)

package com.itheima.demo07SerializableStream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

/*
    java.io.ObjectInputStream:对象的反序列化流 extends InputStream:字节输入流
    作用:把文件中保存的对象,以流的方式读取出来
    构造方法:
        ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。
        参数:
            InputStream in:传递字节输入流,可以传递InputStream的任意的子类对象
     特有的成员方法:
        Object readObject() 从 ObjectInputStream 读取对象。
     实现步骤(重点):
        1.创建ObjectInputStream对象,构造方法中传递FileInputStream对象
        2.使用ObjectInputStream对象中的方法readObject,读取文件中保存的对象
        3.释放资源
     注意:
        public final Object readObject() throws IOException, ClassNotFoundException
        readObject声明抛出了两个异常对象
        ClassNotFoundException:class文件找不到异常
        反序列化有两个前提: 1.类实现Serializable接口 2.有Person.class文件
 */
public class Demo02ObjectInputStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1.创建ObjectInputStream对象,构造方法中传递FileInputStream对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\person.txt"));
        //2.使用ObjectInputStream对象中的方法readObject,读取文件中保存的对象
        Object obj = ois.readObject();
        System.out.println(obj);
        Person p = (Person)obj;
        System.out.println(p.getName()+"\t"+p.getAge());
        //3.释放资源
        ois.close();
    }
}

在这里插入图片描述

4.transient:瞬态关键字

transient:瞬态关键字
作用:阻止成员变量序列化
private transient int age;
oos.writeObject(new Person("小美女",18));
Object obj = ois.readObject();Person{name='小美女', age=0}

static:静态关键字
作用:序列化的是对象,static修饰的成员变量也不能被序列化,不属于对象,被对象所共享
private static int age;
oos.writeObject(new Person("小美女",18));
Object obj = ois.readObject();Person{name='小美女', age=0}

5.序列号冲突异常(面试-扩展)

在这里插入图片描述

public class Person implements Serializable{
    /*
        修改了类的定义:会重新生成序列号,导致反序列化抛出InvalidClassException异常
        解决:
        可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:
        static final long serialVersionUID = 42L;
        final:变量被final修饰,就是一个常量,无论类如何修改,值是固定的
     */
    private static final long serialVersionUID = 1L;
}

6. 练习:序列化集合

package com.itheima.demo07SerializableStream;

import java.io.*;
import java.util.ArrayList;

/*
    练习:序列化集合
 */
public class Demo03Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        show02();
    }

    /*
        序列化集合,反序列化集合
     */
    private static void show02() throws IOException, ClassNotFoundException {
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("张三",18));
        list.add(new Person("李四",18));
        list.add(new Person("王五",18));
        list.add(new Person("赵六",18));
        list.add(new Person("田七",18));
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\list02.txt"));
        oos.writeObject(list);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\list02.txt"));
        Object obj = ois.readObject();
        //向下转型为ArrayList集合
        ArrayList<Person> list02 = (ArrayList<Person>)obj;
        for (Person p : list02) {
            System.out.println(p);
        }
        ois.close();
    }

    /*
        使用ObjectOutputStream写多个对象到文件中
        使用ObjectInputStream读取写入的多个对象
     */
    private static void show01() throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\list01.txt"));
        oos.writeObject(new Person("张三",18));
        oos.writeObject(new Person("李四",18));
        oos.writeObject(new Person("王五",18));
        oos.writeObject(new Person("赵六",18));
        oos.writeObject(new Person("田七",18));
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\list01.txt"));
        Object obj = ois.readObject();
        System.out.println(obj);//Person{name='张三', age=18}
        System.out.println(ois.readObject());//Person{name='李四', age=18}
        System.out.println(ois.readObject());//Person{name='王五', age=18}
        System.out.println(ois.readObject());//Person{name='赵六', age=18}
        System.out.println(ois.readObject());//Person{name='田七', age=18}
        System.out.println(ois.readObject());//EOFException 当输入过程中意外到达文件或流的末尾时,抛出此异常。

        ois.close();
    }
}

总结:

  • 什么时候使用字符流:读写文本文件,以字符(中文,英文,数组,符号)方式读取写入方便
  • 什么使用字节流:读写文件,是非文本文件(图片,视频…)
  • 什么时候使用缓冲流:为了提高读写的效率
  • 什么时候使用转换流:读写非UTF-8编码的文件
  • 什么时候使用序列化流:读写对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值