IO流——IO概述 & 字节流 & 字节缓冲流

IO概述 & 字节流 & 字节缓冲流

1. IO流

1.1概述

  • IO:顾名思义,I就是Input输入,O就是Output输出
  • 流:流是一种抽象概念,是对数据传输的总称。其本质是数据传输

1.2 应用

  • IO流是用来处理设备间数据传输问题的,常应用于:
    • 文件复制
    • 文件上传
    • 文件下载

1.3 分类

按数据的流向按数据类型
输入流:读数据字节流
输出流:写数据字符流
  • 一般来说,我们说IO流的分类是按照数据类型来分的
  • 那么在现实情况中,我们该如何选择字符流和字节流呢?
    • 如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就用字符流
    • 否则就用字节流,在不知道如何选择字符流和字节流时,就使用字节流
1.4 使用场景
  • 操作的是纯文本文件 --> 字符流
  • 操作的是图片、视频、音频等二进制文件 --> 字节流
  • 不确定文件类型 -->优先字节流 <-- 万能的流

2. 字节流

2.1 抽象基类

类名说明
InputStream这个抽象类是表示字节输入流的所有类的超类
OutputStream这个抽象类是表示字节输出流的所有类的超类
  • 子类名称都是以其父类名作为子类名的后缀

2.2 FileOutputStream

2.2.1 概述
  • 字节输出流,用于将数据写入File
  • 创建字节输出流对象:
  FileOutputStream (String name) :创建文件输出流以指定的名称写入文件
  FileOutputStream fos = new FileOutputStream("iodemo\\demo.txt"); 
/*
做了三件事:
   调用系统功能创建了文件
   创建了字节输出流对象
   让字节输出流对象指向创建好的文件
*/
2.2.2 步骤
  • 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)

  • 调用字节输出流对象的写数据方法

  • 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)

2.2.3 方法
方法名说明
void write(int b)将指定的字节写入此文件输出流
一次写一个字节数据
void write(byte[] b)将 b.length字节从指定的字节数组写入此文件输出流
一次写一个字节数组数据
void write(byte[] b, int off, int len)将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
一次写一个字节数组的部分数据
2.2.4 代码示例
  • 一次写一个字节
import java.io.FileOutputStream;
import java.io.IOException;
//一次写一个字节
public class Demo01 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("iodemo\\demo.txt");
        //将指定的字节写入此文件输出流
        // void write(int b)
        fos.write(99);
        fos.write(98);
        //最后都要释放资源
        fos.close();
    }
}
// 结果在文件中写入 cb
  • 一次写一个字节数据数组
import java.io.FileOutputStream;
import java.io.IOException;
//一次写入一个字节数组数据
public class Demo02 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("iodemo\\demo.txt");
        //方法1
        //创建一个字节数组
        byte[] bys = {97,98,99};
        fos.write(bys);
        //方法2
        ///byte[] getBytes():返回字符串对应的字节数组
        byte[] bys1 = "abc".getBytes();
        fos.write(bys1);
        //方法3
        fos.write("abc".getBytes());
        fos.close();
    }
}
  • 一次写一个字节数组的部分数据
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("iodemo\\demo.txt");

        ///byte[] getBytes():返回字符串对应的字节数组
        byte[] bys1 = "abcde".getBytes();
        fos.write(bys1,0, bys1.length); //写入abcde
        //1,3 --> 第二个字节开始,写入三个字节 即从 b 开始
        fos.write(bys1,1, 3); //写入bcd

        fos.close();
    }
}
2.2.5 注意事项
  • 实现换行
系统换行符
windows\r\n
linux\n
mac\r
  • 每一次运行,写入内容都会从开头开始,如何实现追加写入
    • public FileOutputStream (String name,boolean append)
    • 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        //第二个参数一定要为true
        FileOutputStream fos = new FileOutputStream("iodemo\\demo.txt",true);
        ///byte[] getBytes():返回字符串对应的字节数组
        byte[] bys1 = "abcde".getBytes();
        fos.write(bys1,0, bys1.length);
        fos.write(bys1,1, 3);
        fos.close();
    }
}

2.3 FileInputStream

2.3.1 概述
  • 从文件系统中的文件获取输入字节
  • 创建字节输入流
//FileInputStream (String name)
FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
2.3.2 步骤
  • 创建字节输入流对象

  • 调用字节输入流对象的读数据方法

  • 释放资源

2.3.3 方法
方法名说明
public int read()从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止
public int read(byte[] b)从该输入流读取最多b.length个字节的数据为字节数组
public int read(byte[] b,int off,int len)从该输入流读取高达len字节的数据到字节数组,可读部分数据
2.3.4 代码示例
  • 一个读一个字节数据
import java.io.FileInputStream;
import java.io.IOException;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        //FileInputStream (String name)
        FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
        //一次读一个字节数据
        System.out.println(fis.read());
        System.out.println(fis.read());
        System.out.println(fis.read());
        //文本中只有数据abc
        System.out.println(fis.read());//如果abc以及被读完,没数据了,便会输出-1
        System.out.println(fis.read());//-1
        //释放资源
        fis.close();
    }
}
  • 一次读一个字节数组
public class Demo02 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
        //一次读取一个字节数组
        byte[] bys = new byte[3];
        int len;
        while ((len = fis.read(bys)) != -1){
            System.out.println(new String(bys));
            //通常会这么写,使得更加严谨
            //System.out.println(new String(bys,0,len));
        }
    }
}
  • 一次都一个字节数组的部分数据
import java.io.FileInputStream;
import java.io.IOException;

public class Demo03 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
        //一次读取一个字节数组的部分数据
        byte[] bys = new byte[3];
        int len;
        while ((len = fis.read(bys)) != -1){
            System.out.println(new String(bys,1,2));
        }
    }
}

2.4 案例

2.4.1 复制文本文件
  • 一次读写一个字节数据
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//一次读写一个字节数据
public class Test02 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
        FileOutputStream fos = new FileOutputStream("iodemo\\copy.txt");

        int by;
        while ((by = fis.read())!= -1){
            fos.write(by);
        }
        fos.close();
        fis.close();
    }
}
  • 一次读写一个字节数组数据
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//一次读写一个字节数组数据
public class Test01 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
        FileOutputStream fos = new FileOutputStream("iodemo\\copy.txt");

        byte[] bys = new byte[1024]; //一般为1024 及其倍数
        int len;
        //fis.read(bys) --> 括号中的bys一定不能忘了,这里是将读取到的数据存入bys数组
        //判断其不等于-1 是因为如果没有数据 读取就会输出-1 以此作为结束循环的条件
        while ((len = fis.read(bys)) != -1){
            fos.write(bys,0,len);
        }
        fos.close();
        fis.close();
    }
}
2.4.2 复制图片
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

//复制图片
public class Test03 {
    public static void main(String[] args) throws IOException {
    //创建字节输入 输出流对象
        FileInputStream fis = new FileInputStream("E:\\Java_test\\java\\qinqin.gif");
        FileOutputStream fos = new FileOutputStream("iodemo\\qinqin.gif");
    //读取数据源文件
        byte[] bys = new byte[1024];
        int len;
        while ((len = fis.read(bys))!=-1){
        //将读取的字节数组写入目的文件
            fos.write(bys,0,len);
        }
        fis.close();
        fos.close();
    }
}

3. 字节缓冲流

3.1 概述

类名说明
BufferOutputStream该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
BufferedInputStream创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节

3.2 构造方法

方法名说明
BufferedOutputStream(OutputStream out)创建字节缓冲输出流对象
BufferedInputStream(InputStream in)创建字节缓冲输入流对象
  • 为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
    • 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作

3.3 代码示例

3.3.1 字节缓冲输出流
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo02 {
    public static void main(String[] args) throws IOException {
        //创建字节缓冲输出流对象
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("iodemo\\demo.txt"));
        //写入数据
        bos.write("hello\r\n".getBytes());
        //public void flush():刷新缓冲输出流
        //如果没有使用这个方法,数据不会写入文件
        bos.flush();
        bos.write("world\r\n".getBytes());
        bos.flush();
        //释放资源
        //当尚未关闭时, close方法的FilterOutputStream调用其flush方法,然后调用其底层输出流的close方法
        bos.close();
        /*
        区别flush 和 close
          二者都会刷新缓冲输出流
          但是flush刷新完后可以继续添加内容
          close刷新完后就会释放资源,无法再进行添加内容
         */
    }
3.3.2 字节缓冲输入流
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class Demo01 {
    public static void main(String[] args) throws IOException {
/*        FileInputStream fis = new FileInputStream("iodemo\\demo.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);*/
        //终极二合一 ,以后直接这么写
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("iodemo\\demo.txt"));

/*        //一次读取一个字节数据
        int by;
        while ((by = bis.read())!=-1){
            System.out.print((char) by); //注意这里使用的是print
        }*/
        //一次读取一个字节数组
        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys))!= -1){
            System.out.println(new String(bys,0,len));
        }
        //释放资源
        bis.close();
    }
}

3.4 案例

3.4.1 复制视频
  • 四种方法
    • 使用基本字节流一次读写一个字节数据
    • 使用基本字节流一次读写一个字节数组
    • 使用字节缓冲流一次读写一个字节数据
    • 使用字节缓冲流一次读写一个字节数组(效率最高)
import java.io.*;
//这里只写使用字节缓冲流一次读写一个字节数组
public class Test01 {
    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();
        //创建字节缓冲输入 输出流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\Java_test\\keai.mp4"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("iodemo\\keai.mp4"));

        //使用字节缓冲流一次读写一个字节数组
        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys))!=-1){
            bos.write(bys,0,len);
        }

        //释放资源
        bis.close();
        bos.close();

        long end = System.currentTimeMillis();
        //利用System类下的currentTimeMillis()方法测试运行时间 可以用来比较四种方法耗时长短
        System.out.println("耗时:" + (end-start) + "ms");
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值