Day16-【Java SE进阶】IO流(二):字符流、缓冲流、转换流、打印流、数据流、序列化流、IO框架

一. 字符流

字节流:适合复制文件等,不适合读写文本文件

字符流:适合读写文本文件内容

1. FileReader(文件字符输入流)

作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。读取单个字符,性能比较差,一次读取多哥字符,性能还是不错的鸭。

java 复制代码
package com.file;

import java.io.FileReader;
import java.io.Reader;

public class FileTest12 {
    public static void main(String[] args) {
        try (
                //1、创建一个文件字符输入流管道与源文件接通
                Reader fr = new FileReader("day07/src/com/file/test/test.txt");
        ) {
            System.out.println("===一次读取一个字节===");
            int c;
            while ((c=fr.read())!=-1){
                char temp = (char) c;
                System.out.print(temp);
            }
            System.out.println("\r\n===一次读取多个字节===");
            char[] chars = new char[3];
            //2、读取文本文件的内容
            //记住每次读取的字符个数
            int read;
            while ((read=fr.read(chars))!=-1){
                String s = new String(chars, 0, read);
                System.out.print(s);
            }
        }catch (Exception exception){
            exception.printStackTrace();
        }
    }
}

2. FileWriter(文件字符输出流)

作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。

  • 字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
    • 数据会先写到缓冲区里面,最后通过机制调用一次直接写出到磁盘中,性能会变好的
      • 刷新流:flush方法,刷新后流还可以继续使用的,缓冲区装满好会自动flush,缓冲区强制刷新到输出文件中
      • 关闭流:close方法 包含刷新流 关闭后流不可以继续使用了

字节流、字符流的使用场景小结

  • 字节流适合做一切文件数据的拷贝(音视频,文本);字节流不适合读取中文内容输出符流适合做文本文件的操作(读,写)。


java 复制代码
package com.file;

import java.io.FileWriter;
import java.io.Writer;

public class FileTest13 {
    public static void main(String[] args) {
        //加true就是追加数据管道,不加就是覆盖数据管道的
        try (Writer fileWriter = new FileWriter("day07/src/com/file/test/outWriter.txt",true);) {
            // 1、public void write(int c):写一个字符出去
            fileWriter.write(65);
            fileWriter.write('A');
            fileWriter.write('牛');
            fileWriter.write("\r\n");
            // 2、public void write(string c)写一个字符串出去
            fileWriter.write("我是大帅逼");
            fileWriter.write("\r\n");
            // 3、public void write(String cint pos ,int len):写字符串的一部分出去
            fileWriter.write("我是大帅逼知道吗", 0, 5);
            fileWriter.write("\r\n");
            // 4、public void write(char[] buffer):写一个字符数组出去
            char[] chars = {'a', '我', '牛', '比'};
            fileWriter.write(chars);
            fileWriter.write("\r\n");
            // 5、public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
            fileWriter.write(chars, 1, 3);
            fileWriter.write("\r\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

二. 缓冲流

对原始流进行包装,以提高原始流读写数据的性能

1. 字节缓冲流 BufferedInputStream BufferedOutputStream

原始流:

包装流:

  • 原理:字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池

java 复制代码
package com.file;

import java.io.*;

public class FileTest14 {
    public static void main(String[] args) {
        try (InputStream is = new FileInputStream("day07/src/com/file/test/49.jpg");
             //1、定义一个字节缓冲输入流包装原始的字节输入流
             InputStream bis = new BufferedInputStream(is);
             OutputStream os = new FileOutputStream("day07/src/com/file/test/51.jpg");
             //2、定义一个字节缓冲输出流包装原始的字节输出流 可以自定义缓冲池大小的
             BufferedOutputStream bos = new BufferedOutputStream(os, 8192 * 2);) 
        {
            int read;
            byte[] buffer = new byte[1024];
            while ((read = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, read);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 字符缓冲流

BufferedReader

  • 作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。

java 复制代码
package com.file;

import java.io.*;

public class FileTest15 {
    public static void main(String[] args) {
        try (
                Reader fr = new FileReader("day07/src/com/file/test/outWriter.txt");
                BufferedReader br = new BufferedReader(fr)
        ) {
//            char[] buffer = new char[1024];
//            int len;
//           while ((len=br.read(buffer))!=-1){
//               String s = new String(buffer, 0, len);
//               System.out.print(s);
//           }
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(br.readLine());
            }

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

BufferedWriter(字符缓冲输出流)

  • 作用:自带8K(8192)的字符缓冲池,可以提高字符输出流写字符数据的性能





原始流、缓冲流的性能分析[重点]

当字节数组达到一定程度时就不明显了

3. 转换流

  • 如果代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码!
  • 如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码!
    字符输入转换流
  • 解决不同编码时,字符流读取文本内容乱码的问题。
  • 解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。

java 复制代码
package com.file;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class FileTest17 {
    public static void main(String[] args) {
        try (
                //1.得到文件的原始字节流
                InputStream is = new FileInputStream("day07/src/com/file/test/test.txt");
                //2.把原始的字节输入流按照指定的字符集编码转换成字符输入流
                InputStreamReader isr = new InputStreamReader(is,"GBK");
                //3.把字符输入流包装成缓冲字符输入流
                BufferedReader br = new BufferedReader(isr)
        ) {
            String line;
            while ((line=br.readLine())!=null){
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

字符输出转换流

控制写出的编码格式

  • 作用:可以控制写出去的字符使用什么字符集编码。
  • 解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。
java 复制代码
package com.file;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

public class FileTest18 {
    public static void main(String[] args) {
        try (OutputStream os = new FileOutputStream("day07/src/com/file/test/test.txt",true);
             OutputStreamWriter osw = new OutputStreamWriter(os, "GBK");
             BufferedWriter bw = new BufferedWriter(osw)
        ) {
            bw.write("我是一只小猪猪");
            bw.newLine();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

4. 打印流

  • 作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去

java 复制代码
package com.file;

import java.io.PrintStream;

public class FileTest19 {
    public static void main(String[] args) {


        //1.创建一个打印流管道
        try (
//                PrintStream ps = new PrintStream("day07/src/com/file/test/testPrint.txt",
//                        Charset.forName("GBK"));
                PrintStream ps = new PrintStream("day07/src/com/file/test/testPrint.txt");
                ) {
            ps.println(97);
            ps.println('a');
            ps.println("我爱你中国abc");
            ps.println(true);
            ps.println(99.5);
            ps.write(97);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


两者差别不大,打印功能完全一样的;只是在写数据上一个写字节一个写字符的!使用低级流包装可以append

java 复制代码
package com.file;

import java.io.FileOutputStream;
import java.io.PrintWriter;

public class FileTest19 {
    public static void main(String[] args) {


        //1.创建一个打印流管道
        try (
//                PrintStream ps = new PrintStream("day07/src/com/file/test/testPrint.txt",
//                        Charset.forName("GBK"));
                PrintWriter ps = new PrintWriter(new FileOutputStream("day07/src/com/file/test/testPrint.txt",true));
                ) {
            ps.println(97);
            ps.println('a');
            ps.println("我爱你中国abc");
            ps.println(true);
            ps.println(99.5);
            ps.write(97);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


打印流的一种应用:输出语句的重定向。

可以把输出语句的打印位置改到某个文件中去。

java 复制代码
package com.file;

import java.io.PrintStream;

public class FileTest20 {
    public static void main(String[] args) {
        try (PrintStream printStream = new PrintStream("day07/src/com/file/test/testPrint.txt");
        ) {
            System.setOut(printStream);
            System.out.println("我改变了打印流到文件中去啦!");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

5. 数据流


DataOutputstream(数据输出流)

  • 允许把数据和其类型一并写出去。


    DatalnputStream(数据输入流)
    用于读取数据输出流写出去的数据。
java 复制代码
package com.file;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class FileTest21 {
    public static void main(String[] args) {
        try (
                DataOutputStream dos = new DataOutputStream(
                        new FileOutputStream("day07/src/com/file/test/dos.txt", true));
                FileInputStream is = new FileInputStream("day07/src/com/file/test/dos.txt");
                DataInputStream dis = new DataInputStream(is)
        ) {
            dos.writeUTF("我是写数据字符串的");
            dos.writeByte(97);
            dos.writeBoolean(true);
            dos.writeDouble(97.4);
            dos.writeInt(97);
            System.out.println(dis.readUTF());
            System.out.println(dis.readByte());
            System.out.println(dis.readBoolean());
            System.out.println(dis.readDouble());
            System.out.println(dis.readInt());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6. 序列化流

  • 对象序列化:把Java对象写入到文件中去
  • 对象反序列化:把文件里的Java对象读出来


0bjectOutputstream(对象字节输出流)

  • 可以把Java对象进行序列化:把Java对象存入到文件中去。

注意:对象如果要参与序列化,必须实现序列化接口(java.io.Serializable)

Objectlnputstream(对象字节输入流)

可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来。

java 复制代码
package com.file;

import java.io.*;

public class FileTest22 {
    public static void main(String[] args) {
//        serializabledObject();
        unSerializabledObject();
    }
    public static void serializabledObject(){
        //1.创建一个java对象
        User tom = new User("Tom", "123", 12);
        //2.创建一个对象字节输出包装原始字节输出流
        try (
                FileOutputStream fs = new FileOutputStream("day07/src/com/file/test/dos.txt");
                ObjectOutputStream oos = new ObjectOutputStream(fs);
        ) {
            oos.writeObject(tom);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void unSerializabledObject(){
        try (
                FileInputStream fs = new FileInputStream("day07/src/com/file/test/dos.txt");
                ObjectInputStream oos = new ObjectInputStream(fs);
        ) {
            User o =  (User)oos.readObject();
            System.out.println(o);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class User implements Serializable {
    private String uname;
    //加入transient不参与序列化
    private transient String pwd;
    private int age;

    public User() {
    }

    public User(String uname, String pwd, int age) {
        this.uname = uname;
        this.pwd = pwd;
        this.age = age;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "uname='" + uname + '\'' +
                ", pwd='" + pwd + '\'' +
                ", age=" + age +
                '}';
    }
}

如果要一次序列化多个对象,咋整?

  • 用一个ArrayList集合存储多个对象,然后直接对集合进行序列化即可
  • 注意:ArrayList集合已经实现了序列化接口!

7. IO框架

  • 解决某类问题,编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。
  • 好处:在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率
  • 框架的形式:一般是把类、接口等编译成class形式,再压缩成一个,jar结尾的文件发行出去

什么是IO框架

  • 封装了java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。

Commons-io

Commons-io是apache开源基金组织提供的一组有关10操作的小框架,目的是提高I0流的开发效率。

右键项目 新建Directory,取名为lib等名称,然后右键lib为add to lib即可导入成功啦

java 复制代码
package com.file;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class FileTest23 {
    public static void main(String[] args) throws IOException {
        File file = new File("day07/src/com/file/test/49.jpg");
        File file1 = new File("day07/src/com/file/test/100.jpg");
        FileUtils.copyFile(file,file1);
//        java提供的原生
        Files.copy(Path.of("day07/src/com/file/test/49.jpg"),Path.of("day07/src/com/file/test/102.jpg"));
        String s = Files.readString(Path.of("day07/src/com/file/test/out.txt"));
        System.out.println(s);
    }
}
相关推荐
程序员南飞1 小时前
ps aux | grep smart_webrtc这条指令代表什么意思
java·linux·ubuntu·webrtc
弥琉撒到我1 小时前
微服务swagger解析部署使用全流程
java·微服务·架构·swagger
一颗花生米。2 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼2 小时前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐012 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
通信仿真实验室3 小时前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&3 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
ok!ko5 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_857589366 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰6 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin