字符流,以及序列化

这一块的内容主要是有关字符流,以及序列化的内容。

编码表

由字符及其对应的数值组成的一张表

通过字符集解码字符数组

  • public String(byte[] bytes,Charset charset)
  • public byte[] getBytes(Charset charset)
    总结:
    编码:把看的懂的变成看不懂的,类似于加密
    String – byte[]
    解码:把看不懂的变成看的懂的,根据编码表
    byte[] – String
public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "晚上";
        //String -- byte[]
        byte[] gbk = s.getBytes("GBK");
        for(byte b:gbk){
            System.out.println(b);
        }
        System.out.println("************************");
        byte[] utf = s.getBytes("UTF-8");
        for(byte b1:utf){
            System.out.println(b1);
        }
        System.out.println("************************");
        byte[] unicodes = s.getBytes("Unicode");
        for (byte b2:unicodes) {
            System.out.println(b2);
        }
        System.out.println("************************");
        //byte[] -- String
        String s1 = new String(unicodes,"Unicode");
        System.out.println(s1);
    }
//-51
//-19
//-55
//-49
//************************
//-26
//-103
//-102
//-28
//-72
//-118
//************************
//-2
//-1
//102
//90
//78
//10
//************************
//晚上

字符流(也叫做转换流)

字符流 = 字节流 + 编码表

字符输出流

  • public OutputStreamWriter(OutputStream out)
    根据默认的编码用字符作为桥梁将字节流的数据转换成字符流
  • public OutputStreamWriter(OutputStream out,String charsetName)
    根据指定的编码用字符作为桥梁将字节流的数据转换成字符流
public static void main(String[] args) throws IOException {
        //设置写出的编码格式
//        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("b.txt"),
//                "GBK");
//        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("b.txt"),
//                "UTF-8");
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("b.txt"),
                "Unicode");

        outputStreamWriter.write("中华人民共和国万岁");

        outputStreamWriter.close();
    }

OutputStreamWriter写数据

  • public void write(int c)
  • public void write(char[] cbuf)
  • public void write(char[] cbuf,int off,int len)
  • public void write(String str)
  • public void write(String str,int off,int len)

注意:close()与flush()的区别:

  • close()关闭流对象,但是会先刷新一次缓冲区。关闭之后,就不能调用
  • flush()仅仅只是刷新,刷新之后还能继续调用
public static void main(String[] args) throws IOException {
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("b.txt"));

        //public void write(int c)
        //写数字,写进去的是ASCII码
//        outputStreamWriter.write(99);
//        outputStreamWriter.flush();


//        public void write(char[] cbuf)
        //写字符数组,写进去的是每个字符
//        char[] chars = new char[]{'a','b','c','d'};
//        outputStreamWriter.write(chars);


        //public void write(char[] cbuf,int off,int len)
        //写字符数组,带着偏移量;写进去的是每个字符,带着偏移量
//        char[] chars = new char[]{'a','b','c','d'};
//        outputStreamWriter.write(chars,0,2);


        //public void write(String str)
        //写字符串,写进去的是字符串
//        String s = "helloworld";
//        outputStreamWriter.write(s);


        //public void write(String str,int off,int len)
        //写字符串,带着偏移量;写进去的是字符串,带着偏移量
        String s = "helloworld";
        outputStreamWriter.write(s,0,4);
        outputStreamWriter.flush();
        
        outputStreamWriter.close();
    }

字符输入流

  • public InputStreamReader(InputStream in)
    读取数据,根据默认的编码用字符作为桥梁将字节流数据转换成字符流
  • public InputStreamReader(InputStream in,String charsetName)
    读取数据,根据指定的编码用字符作为桥梁将字节流数据转换成字符流
public static void main(String[] args) throws IOException {
//        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("b.txt"));
//        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("b.txt"),
//                "GBK");
//        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("b.txt"),
//                "Unicode");
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("b.txt"),
                "UTF-8");
        
        //一次读取一个字符
        int b = 0;
        while ((b = inputStreamReader.read()) != -1){
            System.out.print((char) b);
        }

        inputStreamReader.close();
    }

InputStreamReader读数据

  • public int read() 一次只读一个字符
  • public int read(char[] cbuf) 一次只读一个字符数组
public static void main(String[] args) throws IOException {
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("b.txt"));

        //一次只读取一个字符
//        int b = 0;
//        while ((b = inputStreamReader.read()) != -1){
//            System.out.println((char)b);
//        }

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

使用字符流实现文本文件的复制

public static void main(String[] args) throws IOException {
        /*
        将当前项目目录下的a.txt内容复制到当前目录下
        数据源:
            a.txt -- 读取数据 -- 字符流 -- InputStreamReader
        目的地:
            aCopy.txt -- 写出数据 -- 字符流 -- InputStreamWriter
         */

        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("a.txt"));
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("aCopy.txt"));

        //读写数据
        //第一种方式 只读取一个字符
//        int b = 0;
//        while ((b = inputStreamReader.read()) != -1){
//            outputStreamWriter.write(b);
//            outputStreamWriter.flush();
//        }

        //第二种方式 读取一个字符数组
        int len = 0;
        char[] chars = new char[1024];
        while ((len = inputStreamReader.read(chars)) != -1){
            outputStreamWriter.write(chars,0,len);
            outputStreamWriter.flush();
        }
        
        outputStreamWriter.close();
        inputStreamReader.close();
    }

使用字符流简化书写的方式复制文本文件

简化方式:FileReader、FileWriter

由于我们常见的操作都是使用本地默认的编码,我们基本上在使用的时候不去指定编码,而又因为字符流的名称有点长,所以Java就提供了子类给我们使用

字符流 = 字节流 + 编码表

OutputStreamWriter = FileOutputStream + 编码表
InputStreamReader = FileInputStream + 编码表

public static void main(String[] args) throws IOException {
        //原先的写法
//        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("a.txt"));
        //改进的写法
        FileReader fileReader = new FileReader("a.txt");

        //原先的写法
//        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("aCopy.txt"));
        //改进的写法
        FileWriter fileWriter = new FileWriter("aCopy.txt");


        //第一种方式     一次只读取一个字符
//        int b = 0;
//        while ((b = fileReader.read()) != -1){
//            fileWriter.write(b);
//            fileWriter.flush();
//        }

        //第二种方式     一次只读取一个字符数组
        int len = 0;
        char[] chars = new char[1024];
        while ((len = fileReader.read(chars)) != -1){
            fileWriter.write(chars,0,len);
            fileWriter.flush();
        }
        
        fileWriter.close();
        fileReader.close();
    }

字符缓冲流

  • BufferedWriter:字符缓冲输出流
    • 将文本文件写入到字符输入流,缓冲各个字符,以提供单个字符,数组和字符串的高效写入。
    • 可以指定缓冲区大小,或者接受默认大小
    • 默认值足够大,可以不用再去指定了
public static void main(String[] args) throws IOException {
        //原本的写法
//        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));
        //改进的写法
        BufferedWriter bufferedWriter1 = new BufferedWriter(new FileWriter("a.txt"));

        bufferedWriter1.write("hello");
        bufferedWriter1.write("world");

        bufferedWriter1.flush();

        bufferedWriter1.close();
    }
  • BufferedReader:字符缓冲输入流
    • 从字符输入流读取文本,缓冲字符,以提供字符,数组或行的高效读取
    • 可以指定缓冲区的大小,或者可以使用默认大小
    • 默认值足够大,不需要再做改变
public static void main(String[] args) throws IOException {
        //原本的写法
//        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
        //改进的写法
        BufferedReader bufferedReader1 = new BufferedReader(new FileReader("a.txt"));

        //方式一,一个字符的读取
//        int b = 0;
//        while ((b = bufferedReader1.read()) != -1){
//            System.out.println((char)b);
//        }

        //方式二,一个字符数组的读取
        char[] chars = new char[1024];
        int len = 0;
        while ((len = bufferedReader1.read(chars)) != -1){
            System.out.println(new String(chars,0,len));
        }
        
        bufferedReader1.close();
    }

字符缓冲流复制文本文件

public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("aCopy.txt"));

        //一次读取一个字符
        int b = 0;
        while ((b = bufferedReader.read()) != -1){
            bufferedWriter.write(b);
            bufferedWriter.flush();
        }

//        一次读取一个字符数组
        int len = 0;
        char[] chars = new char[1024];
        while ((len = bufferedReader.read(chars)) != -1){
            bufferedWriter.write(chars,0,len);
            bufferedWriter.flush();
        }

        bufferedWriter.close();
        bufferedReader.close();
    }

字符缓冲流的特殊功能

  • BufferedWriter:void newLine()
    写一行行分隔符,根据系统决定换行符的
    行分隔符字符串由系统属性line.separator定义,并不一定是单个换行符(’\n’)字符
  • BufferedReader:void readLine()
    读一行文字,一次读取一行数据
    一行被视为由换行符(’\n’),
    回车符(’\r’)中的任何一个或者随后的换行符终止
    包含行的内容的字符串,不包含任何终止字符,如果达到流的末尾,则为null
public static void main(String[] args) throws IOException {
        write();
        read();
    }

    public static void read() throws IOException {
        //创建字符缓冲流
        BufferedReader bufferedReader = new BufferedReader(new FileReader("a.txt"));
        //public String readLine()      读一行文字,一次读取一行数据
//        String s = bufferedReader.readLine();
//        System.out.println(s);

        //最终版本
        String line = null;
        while ((line = bufferedReader.readLine()) != null){
            System.out.println(line);
        }

        bufferedReader.close();
    }
    public static void write() throws IOException{

        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("a.txt"));
        for(int i=0;i<10;i++){
            bufferedWriter.write("大数据");
            bufferedWriter.newLine();//换行
            bufferedWriter.flush();
        }

        bufferedWriter.close();
    }

字符缓冲流的特殊功能复制文本文件

public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader("a.txt"));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("aCopy.txt"));

        String s = null;
        while ((s = bufferedReader.readLine()) != null){
            bufferedWriter.write(s);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        bufferedWriter.close();
        bufferedReader.close();
    }

有关字符流、字节流的小练习

复制图片,用字节流复制,四种方式

  • 一次读取一个字节
  • 一次读取一个字节数组
  • 字节缓冲流一次读取一个字节
  • 字节缓冲流一次读取一个字节数组(推荐这种写法)
public static void main(String[] args) throws IOException{
        String input = "祥哥.jpg";
        String out = "祥哥复制.jpg";

//        fun1(input,out);
//        fun2(input,out);
//        fun3(input,out);
//        fun4(input,out);
    }
    public static void fun1(String input,String out) throws IOException {
        //一次读取一个字节
        FileInputStream fileInputStream = new FileInputStream(input);
        FileOutputStream fileOutputStream = new FileOutputStream(out);

        int b = 0;
        while ((b = fileInputStream.read()) != -1){
            fileOutputStream.write(b);
            fileOutputStream.flush();
        }

        fileOutputStream.close();
        fileInputStream.close();

    }
    public static void fun2(String input,String out) throws IOException{
        //一次只读取一个字节数组
        FileInputStream fileInputStream = new FileInputStream(input);
        FileOutputStream fileOutputStream = new FileOutputStream(out);

        int len = 0;
        byte[] bytes = new byte[2048];
        while ((len = fileInputStream.read(bytes)) != -1){
            fileOutputStream.write(bytes,0,len);
            fileOutputStream.flush();
        }

        fileOutputStream.close();
        fileInputStream.close();
    }
    public static void fun3(String input,String out) throws IOException{
        //字节缓冲流     一次读取一个字节
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(input));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(out));

        int b = 0;
        while ((b = bufferedInputStream.read()) != -1){
            bufferedOutputStream.write(b);
            bufferedOutputStream.flush();
        }


        bufferedOutputStream.close();
        bufferedInputStream.close();

    }
    public static void fun4(String input,String out) throws IOException{
        //字节缓冲流,一次只读取一个字符数组
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(input));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(out));

        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = bufferedInputStream.read(bytes)) != -1){
            bufferedOutputStream.write(bytes,0,len);
        }

    }

复制文本文件,使用字符流,五种方式

  • 字符流一次只读取一个字符
  • 字符流一次只读取一个字符数组
  • 字符缓冲流一次只读取一个字符
  • 字符缓冲流一次只读取一个字符数组
  • 字符缓冲流特殊方法读写数据(推荐这种方法实现)
public static void main(String[] args) throws IOException{
        String input = "a.txt";
        String out = "aCopy.txt";
//        fun1(input,out);
//        fun2(input,out);
//        fun3(input,out);
//        fun4(input,out);
        fun5(input,out);

    }

    public static void fun1(String input,String out)throws IOException {
        //一次读取一个字符
//        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(input));
        FileReader fileReader = new FileReader(input);
        FileWriter fileWriter = new FileWriter(out);

        int b = 0;
        while ((b = fileReader.read()) != -1){
            fileWriter.write(b);
            fileWriter.flush();
        }

        fileWriter.close();
        fileReader.close();
    }
    public static void fun2(String input,String out)throws IOException{
        //一次只读取一个字符数组
        FileReader fileReader = new FileReader(input);
        FileWriter fileWriter = new FileWriter(out);

        int len = 0;
        char[] chars = new char[1024];
        while ((len = fileReader.read(chars)) != -1){
            fileWriter.write(chars,0,len);
            fileWriter.flush();
        }

        fileWriter.close();
        fileReader.close();
    }
    public static void fun3(String input,String out)throws IOException{
        //字符缓冲流一次读取一个字符
        BufferedReader bufferedReader = new BufferedReader(new FileReader(input));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(out));

        int b = 0;
        while ((b = bufferedReader.read()) != -1){
            bufferedWriter.write(b);
            bufferedWriter.flush();
        }

        bufferedWriter.close();
        bufferedReader.close();
    }
    public static void fun4(String input,String out)throws IOException{
        //字符缓冲流一次只读取一个字符数组
        BufferedReader bufferedReader = new BufferedReader(new FileReader(input));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(out));

        char[] chars = new char[1024];
        int len = 0;
        while ((len = bufferedReader.read(chars)) != -1){
            bufferedWriter.write(chars,0,len);
            bufferedWriter.flush();
        }

        bufferedWriter.close();
        bufferedReader.close();
    }
    public static void fun5(String input,String out)throws IOException{
        //使用字符缓冲流特殊方法读取数据
        BufferedReader bufferedReader = new BufferedReader(new FileReader(input));
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(out));

        String s = null;
        while ((s = bufferedReader.readLine()) != null){
            bufferedWriter.write(s);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        bufferedWriter.close();
        bufferedReader.close();
    }

把ArrayList集合中的字符串数据存储到文本文件

public static void main(String[] args) throws IOException {

        ArrayList<String> list = new ArrayList<String>();
        list.add("hello");
        list.add("world");
        list.add("java");

        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("a.txt"));

        for(String s : list){
            bufferedWriter.write(s);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        bufferedWriter.close();
    }

键盘录入五个学生信息(姓名,语数英成绩)按总分高低存入文本文件

public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("a.txt"));

        TreeSet<Student1> treeSet = new TreeSet<>(new Comparator<Student1>() {
            @Override
            public int compare(Student1 o1, Student1 o2) {
                int i = o1.sum() - o2.sum();
                return i;
            }
        });

        Scanner sc = new Scanner(System.in);

        System.out.println("请输入一些学生信息,姓名、语文成绩、英语成绩、数学成绩,#分割,输入exit结束");
        while (true){
            String x = sc.nextLine();
            if ("exit".equals(x)){
                break;
            }

            String[] split = x.split("#");
            Student1 student1 = new Student1(split[0], Integer.parseInt(split[1]), Integer.parseInt(split[2]), Integer.parseInt(split[3]));
            treeSet.add(student1);

        }

        bufferedWriter.write("学生信息如下");
        bufferedWriter.write("姓名\t语文成绩\t英语成绩\t数学成绩");
        bufferedWriter.newLine();
        bufferedWriter.flush();
        for(Student1 s:treeSet){
            bufferedWriter.write(s.getName()+"\t"+s.getChinese()+"\t"+s.getEnglish()+"\t"+s.getMath());
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        bufferedWriter.close();
    }

对文件中一串字符串进行排序之后写入另一个文件

public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("a1.txt"));
        BufferedReader bufferedReader = new BufferedReader(new FileReader("a.txt"));

        String s = bufferedReader.readLine();
        bufferedReader.close();

        char[] chars = s.toCharArray();
        Arrays.sort(chars);

//        String s1 = chars.toString();
        String s1 = new String(chars);

        System.out.println(s1);
        bufferedWriter.write(s1);
        bufferedWriter.newLine();
        bufferedWriter.close();
    }

对IO的一个总结

在这里插入图片描述

序列化

  • 序列化流:把对象按照流一样的方式存到文本文件或者在网络中传输
    对象 – 流数据(ObjectOutputStream)
  • 反序列化:把文本文件中的流对象数据或者网络中的流数据还原成对象
    流数据 – 对象(ObjectInputStream)
/**
 *  未序列化的异常
 *  NotSerializableException: com.shujia.java.day21.Person
 *
 *  类的序列化由实现java.io.Serializable接口的类启用。
 *  不实现此接口的类将不会使任何状态序列化或反序列化。
 *
 *  这个接口没有任何方法,类似于这种没有方法的接口,我们称之为标记接口
 *
 *
 *  InvalidClassException:
 *  com.shujia.java.day21.Person; local class incompatible:
 *  stream classdesc serialVersionUID = 301533426692145378,
 *  local class serialVersionUID = 1370790239890091773
 *
 *  为什么会有这种问题呢?
 *      Person类实现了序列化接口,它本身应该有个标记值
 *      假设这个标记一开始是100.
 *      开始时候:
 *          Person.class --  id=100
 *          write数据:oos.txt -- id=100
 *          read数据:oos.txt -- id=100
 *
 *      现在:
 *          Person.class -- id=200
 *          write数据:oos.txt -- id=100
 *          read数据:osos.txt -- id=100
 *
 * 但是,在实际开发中,需要保留历史数据,不能重新写入,怎么办呢?
 *
 * 由于我们知道的原因是id不匹配,每次修改java程序文件的时候,.class文件都会发生改变,对应的id值也会改变
 * 所以就出现了这个问题。
 * 如果说有一个办法可以让java程序文件的id值是一个固定的值,这样的话就算你再怎么改,id都不会变就更好了。
 *
 *
 *  需求:
 *      我现在不想序列化age成员变量,怎么办呢?
 *      Java提供了这么一个关键字:transient
 *
 *
 *
 * @author xiaohu
 */
public class Person implements Serializable {
    private static final long serialVersionUID = 301533426692145378L;   //加上这个之后,就可以读回来数据,怎么改变都可以了
    private String name;
    private int age;
//    private transient int age;        //有了这个东西之后,就固定了,不被改变,比如写入年龄25,加上这个,就不改变了
//    int age;                  //这里第一次运行的是int age 之后 变成了 private int age 就读不回来了

    public Person() {
    }

    public Person(String name, int age) {

        this.name = name;
        this.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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public static void main(String[] args) {
        //由于我们我们要对对象进行序列化,所以定义一个类
        //序列化数据其实就是将对象持久化
        try {
//            write();
            read();
        } catch (IOException|ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static void read() throws IOException, ClassNotFoundException {
        //创建ObjectInputStream对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));

        //Object readObject()
        //从ObjectInputStream读取一个对象。
        Object o = ois.readObject();

        ois.close();

        System.out.println(o);

    }

    private static void write() throws IOException {
        //创建ObjectOutputStream对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));

        //创建对象
        Person zhangsan = new Person("zhangsan", 24);

        //void writeObject(Object obj)
        //将指定的对象写入ObjectOutputStream。
        oos.writeObject(zhangsan);

        oos.close();
    }

感谢阅读,我是啊帅和和,一位大数据专业即将大四学生,祝你快乐。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊帅和和。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值