JavaSE 进阶:IO 流核心知识点(字节流 vs 字符流 + 缓冲流优化 + 实战案例)

前言

进入javaIO流。在程序运行的时候,所有的变量,数组或者集合等等都是保存在内存中。随着程序的结束或者断电,数据就没有了!

那么,如何永久的存储呢?采用磁盘文件存储。文件在电脑磁盘中保存,即便断电,或者程序终止,文件中的数据也不会丢失。所以我们引入IO流将一些要保存的数据保存到硬盘中。

认识IO流

IO流主要用于连接程序和磁盘文件,传输以字节/字符为单位的数据

IO流的分类

由此可以先将IO流按输入数据的单位分为字节流和字符流

再按照输入输出分先为四类。分别为:

  • 字节输入流 InputStream(读字节数据的)
  • 字节输出流 OutputStream(写字节数据出去的)
  • 字符输入流 Reader(读字符数据的)
  • 字符输出流 Writer(写字符数据出去的)

而后为了增强字符输入输出流的效率,引入了

  • 缓冲字节输入流 BufferedInputstream
  • 缓冲字节输出流 BufferedOutputstream
  • 缓冲字符输入流BufferedReader
  • 缓冲字符输出流BufferedWriter

字节流

多用于读写而不操作数据的地方

字节输入流 InputStream

作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。

基本方法:

注意事项:

  • 使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码。
  • 使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码。
  • 读取文本适合用字符流;字节流适合做数据的转移,比如:文件复制

代码实现:

Java 复制代码
//目标:使用字节输入流读取文件的数据
//1.创建字节输入流对象
FileInputStream input = new FileInputStream("day03-StreamIO/a.txt");

//2.读取字节数据
//2.1 一个字节一个字节读取
int b = input.read();
System.out.println((char) b);//a
b = input.read();
System.out.println((char) b);//b
b = input.read();
System.out.println((char) b);//c
//b = input.read();
//System.out.println((char) b);//乱码

//2.2 读取一个字节数组
byte[] bytes = new byte[3];
input.read(bytes);
System.out.println(new String(bytes));//将字节数组 bytes 转换为字符串表示

//3.关闭流
input.close();
//注意:字节流不适合读取文本内容进行解析展现,因为如果字节断开会乱码。

读取文件为

复制代码
abc编程

字节输出流 OutputStream

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

基本方法:

代码:

Java 复制代码
//目标:使用字节输出流输出数据到目标文件 demo2.txt
//1.创建文件输出流对象
//FileOutputStream output = new FileOutputStream("day03-StreamIO/b.txt");//覆盖方式
FileOutputStream output = new FileOutputStream("day03-StreamIO/b.txt",true);//追加方式

//2.输出数据
//输出一个字节
output.write(97);//a

//输出一个换行
output.write("\n".getBytes());

//输出字节数组全部数据
byte[] bytes = "唐根泰".getBytes();
output.write(bytes);

//输出一个换行
output.write("\n".getBytes());

//输出字节数组一部分数据
output.write(bytes,3,6);//bytes:要传入的数组,3:开始,6:需要传入的长度       这里的意思是从索引3开始往后传6个字节

//输出一个换行
output.write("\n".getBytes());

//3.关闭资源
output.close();

资源释放方案

代码:

Java 复制代码
//目标:使用finally释放资源(传统做法)
//语法:try{
//     }catch(Exception e){
//     }finally{
//           释放资源
//    }
//finally的作用:无论try里面的代码是否发生异常都会执行finally里面的代码,确保有效资源可以释放
FileInputStream in = null;
FileOutputStream out = null;

try {
    //1.创建输入流对象读取1.png
    in = new FileInputStream("day03-StreamIO/1.png");

    //2.创建输出流对象输出到2.png
    out = new FileOutputStream("day03-StreamIO/2.png");

    //3.读取数据并输出
    //3.1 创建1kb字节数组
    byte[] bytes = new byte[1024];

    //3.2 循环读取并写出
    // int length = in.read(bytes); 从输入流中读取1024个字节,如果读取成功会返回读取字节的个数,
    //      返回-1代表没有读取到任何数据
    int length = -1;
    while ((length = in.read(bytes)) != -1) {
        // out.write(bytes);//将字节数组所有数据输出,这个读到最后可能有遗留上一次读取的数据,也会再次输出
        out.write(bytes, 0, length);//推荐方式,读多少输出多少,不会有遗留数据输出
    }
    System.out.println("文件复制成功!");
} catch (IOException e) {
    throw new RuntimeException(e);
} finally {
    try {
        //4.关闭流,推荐从下往上关闭
        if (out != null)
            out.close();
        if (out != null)
            in.close();
        System.out.println("资源关闭成功!");
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
Java 复制代码
//目标:使用jdk8提供最新释放资源方式
//语法:try(资源){
//         逻辑处理
//     }catch(Exception ex){}
//     上面运行后会自动调用资源的close方法,前提资源实现AutoCloseable接口才可以
try (//1.创建输入流对象读取1.png
     FileInputStream in = new FileInputStream("day03-StreamIO/1.png");

     //2.创建输出流对象输出到2.png
     FileOutputStream out = new FileOutputStream("day03-StreamIO/2.png");)
{
    //3.读取数据并输出
    //3.1 创建1kb字节数组
    byte[] bytes = new byte[1024];

    //3.2 循环读取并写出
    // int length = in.read(bytes); 从输入流中读取1024个字节,如果读取成功会返回读取字节的个数,
    //      返回-1代表没有读取到任何数据
    int length = -1;
    while ((length = in.read(bytes)) != -1) {
        // out.write(bytes);//将字节数组所有数据输出,这个读到最后可能有遗留上一次读取的数据,也会再次输出
        out.write(bytes, 0, length);//推荐方式,读多少输出多少,不会有遗留数据输出
    }
    System.out.println("文件复制成功!");
} catch (IOException e) {
    throw new RuntimeException(e);
}

字符流

可以对数据进行操作

字符输入流 Reader

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

基本语法:

代码:

Java 复制代码
// 目标:掌握字符输入流的操作
try (
        //1.创建输入流资源
        FileReader reader = new FileReader("day04-IOThread/a.txt")
) {
    //2.读取一个字符
    int c = reader.read();
    System.out.println((char) c);//a
    c = reader.read();
    System.out.println((char) c);//b
    c = reader.read();
    System.out.println((char) c);//c
    c = reader.read();
    System.out.println((char) c);//唐

    //3.读取一个字符数组
    char[] chars = new char[1024];
    int length = reader.read(chars);
    System.out.println(new String(chars,0,length));
} catch (Exception e) {
    throw new RuntimeException(e);
}

字符输出流 Writer

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

基本方法:

字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效

代码:

Java 复制代码
//目标:掌握字符输出流的操作

try (
    //1.创建字符串输出流对象
    FileWriter writer = new FileWriter("day04-IOThread/a.txt")
){
    //2.写一个字符
    writer.write(97);

    //3.写一个字符串
    String str = "hello world";
    writer.write("\n" + str);

    //4.写一个字符串的一部分
    writer.write("\n" + str,0,6);

    //5.写一个字符数组
    char[] chars = {'a','b','c','唐'};
    writer.write("\n");
    writer.write(chars);

    //6.写一个字符数组的一部分
    writer.write("\n");
    writer.write(chars,0 ,3);
} catch (Exception e) {
    throw new RuntimeException(e);
}

缓冲流

缓冲字节输入流 BufferedInputstream

缓冲字节输出流 BufferedOutputstream

作用:可以提高字节流读写数据的性能 原理:缓冲字节输入流自带了8KB缓冲池;缓冲字节输出流也自带了8KB缓冲池。

代码:

Java 复制代码
//目标:使用高级缓冲字节流实现复制文件
//注意:如果缓存的桶没有满不会立即输出,如果想立即输出flush()或close()方法

try (
        InputStream in = new FileInputStream("day04-IOThread/1.png");
        OutputStream out = new FileOutputStream("day04-IOThread/2.png");

        //创建高级缓冲流
        BufferedInputStream bis = new BufferedInputStream(in,1024*16);//将默认8Kb缓存修改为16KB
        BufferedOutputStream bos = new BufferedOutputStream(out,1024*16);
        ){

    byte[] bytes = new byte[1024];

    //3.2 循环读取并写出
    int length = -1;
    while ((length = bis.read(bytes)) != -1){
        bos.write(bytes,0,length);
        //bos.flush();//不需要,因为流使用完  会自动调用close()方法
    }
    System.out.println("文件复制成功!");
} catch (Exception e) {
    throw new RuntimeException(e);
}

缓冲字符输入流BufferedReader

缓冲字符输出流BufferedWriter

基本语法:

代码:

Java 复制代码
//目标:使用高级缓冲字符流实现复制文件
//注意:如果缓存的桶没有满不会立即输出,如果想立即输出flush()或close()方法

try (
        FileReader in = new FileReader("day04-IOThread/1.txt");
        FileWriter out = new FileWriter("day04-IOThread/2.txt");

        //创建高级缓冲流
        BufferedReader bis = new BufferedReader(in,1024*16);//将默认8Kb缓存修改为16KB
        BufferedWriter bos = new BufferedWriter(out,1024*16);
){

    /*byte[] bytes = new byte[1024];

    //3.2 循环读取并写出
    int length = -1;
    while ((length = bis.read(bytes)) != -1){
        bos.write(bytes,0,length);
        //bos.flush();//不需要,因为流使用完  会自动调用close()方法
    }*/

    //按照行读写
    String result = null;
    while ((result = bis.readLine()) != null){
        bos.write(result);
        //注意:需要手动换行
        bos.newLine();
    }
    System.out.println("文件复制成功!");
} catch (Exception e) {
    throw new RuntimeException(e);
}
相关推荐
okseekw1 小时前
一篇吃透函数式编程:Lambda表达式与方法引用
java·后端
爱装代码的小瓶子1 小时前
【c++知识铺子】最后一块拼图-多态
java·开发语言·c++
认真敲代码的小火龙1 小时前
【JAVA项目】基于JAVA的超市订单管理系统
java·开发语言·课程设计
油丶酸萝卜别吃1 小时前
在springboot项目中怎么发送请求,设置参数,获取另外一个服务上的数据
java·spring boot·后端
7哥♡ۣۖᝰꫛꫀꪝۣℋ1 小时前
SpringBoot 配置⽂件
java·spring boot·后端
TroubleBoy丶1 小时前
Docker可用镜像
java·linux·jvm·docker
a3722107741 小时前
HikariCP配置 高并发下连接泄漏避免
java·数据库·oracle
CaliXz1 小时前
取出51.la统计表格内容为json数据 api
java·javascript·json
带刺的坐椅1 小时前
Solon AI 开发学习16 - generate - 生成模型(图、音、视)
java·ai·llm·openai·solon