IO流

随用随创建!!!!

随用随创建!!!!

随用随创建!!!!

以免数据被覆盖

存储和读取数据的解决方案

I:input O:output

流:像水流一样传输数据

作用:用于读写数据(本地文件,网络)

分类:

  • 流的方向:输入流(读取)、输出流(写出)
  • 操作文件类型:字节流(所有类型的文件)、字符流(纯文本文件)

IO流的体系

字节流

  • InputStream 字节输入流
  • FileInputStream 操作本地文件的字节输入流
  • 操作本地文件的字节输入流,可以把本地文件中的数据读取到代码中
  • 步骤:
  1. 创建对象
  • 如果对象读取的文件不存在,直接报错
  1. 读数据
  • 一次读一个字节,读出来的是ASCLL上对应的数字
  • 读到末尾,read会返回-1
  1. 释放资源
  • OutputStream 字节输出流
  • FileOutputStream 操作本地文件的字节输出流
  • 操作本地文件的字节输出流,可以把程序中的数据写到本地文件中
  • 步骤:
  1. 创建字节流输出对象
  1. 参数可以是字符串表示的罗京或者File对象都是可以的
  2. 如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
  3. 如果文件已经存在,会清空文件内容
  1. 写数据
  1. write方法的参数是整数,但是实际上写到文件上的内容是整数在ASXII码上对应的字符
  1. 释放资源
  1. 每次使用完流后都要释放资源,解除资源的占用
public static void main(String[] args) throws IOException {
        //创建对象
        FileOutputStream fos = new FileOutputStream("E:\\idea-work\\work\\a.txt");
        //写出数据
        fos.write('s');
        //释放资源
        fos.close();
    }
  • 写数据的三种方式:
  1. write(int b) 一次写一个字节数据
  2. write(byte[] b) 一次写一个字节数组数据
  3. write(byte[] b,int off , int len) 一次写一个字节数组的部分数据
  • 可以创建一个字节数组来节省读取和写入的时间,一般情况创建1024的整数倍大小的数组,如果文件较大,一般创建5-10M的数组长度
public static void main(String[] args) throws IOException {
        long stime =System.currentTimeMillis();//开始执行时获取时间

        FileInputStream fis = new FileInputStream("E:\\idea-work\\work\\movie.mp4");
        FileOutputStream fos = new FileOutputStream("E:\\idea-work\\jichu\\jichuyufa\\copy.mp4");

        /*int b;
        while ((b=fis.read())!=-1){
            fos.write(b);
        }  //该程序执行时间为22秒
        */

        int b;
        byte[] bytes = new byte[1024*1024*5];

        while ((b=fis.read(bytes))!=-1){
            fos.write(bytes,0,b);
        }
        //优化后执行时间为9毫秒
        fos.close();
        fis.close();
        long etime =System.currentTimeMillis();//结束后获取时间
        System.out.println(etime-stime);//得出程序执行时间

    }

字符集

  • ASCLL (英文)
  • GBK (英文 中文) 国家标准字符集 系统显示ANSI
  • (英文规则 一个字节)不足8位,前面补0
  • (汉字规则 两个字节)高位字节二进制一定以1开头,转成十进制是一个负数
  • Unicode (英文 中文) 国际标准字符集
  • UTF-16编码规则:用2-4个字节保存
  • UTF-32编码规则:固定4字节保存
  • UTF-8编码规则:用1-4个字节保存 英文字母1个字节,简体中文3个字节
  • 表示方法0xxxxxxx(ASCLL) 1110XXXX 10XXXXXX 10XXXXXXX(中文)

乱码解决方式:

  1. 不要用字节流读取文本文件
  2. 编码解码时使用同一个码表,同一个编码规则

java中编码解码:

  1. 编码 getBytes(参数) 定义参数指定方式编码,没有参数表示默认
  2. 解码 String(bytes,参数) 定义参数指定方式解码,没有参数表示默认

字符流

字符流的底层其实是字节流

  • 特点
  • 输入流:一次读一个字节,遇到中文时,一次读多个字节
  • 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
  • Reader 字符输入流
  • FileReader:操作本地文件的字符输入流
  • 创建对象
  • FileReader() 参数可以为文件路径或者字符串
  • 底层原理
    关联文件,并创建缓冲区
  • 读取数据
  • read() 读取一个或多个,读到末尾返回-1
  • 一次读取一个字节,遇到中文一次读取多个
  • 读取数据解码并转成十进制
  • 底层原理
  1. 判断缓冲区有没有数据可以读取
  2. 缓冲区没有数据,就冲文件尽可能多的读取数据放入缓冲区中,如果文件也没数据时返回-1
  3. 缓冲区中有数据,就冲缓冲区中读取数据
  • 释放资源
  • Writer 字符输出流
  • FileWriter:操作本地文件的字符输出流
  • FileWriter(file,续写开关) 创建输出流关联本地文件
  • writer()写出一个字符、一个字符串或者一个数组
  • 创建对象
  • 底层:创建缓冲区
  • 写出数据
  • 底层:
  1. 先写到缓冲区,当缓冲区满后自动写入目的文件
  2. 使用flush可以手动保存到文件中
  3. 关流之前会扫描缓冲区中有没有数据,如果有自动将数据全部写入目标文件后再断开连接
  4. 调用flush后可以继续写,调用close后就不能继续写数据了
  • 释放资源

缓冲流

  1. 字符缓冲流

BufferedReader(Reader r)

readLine()读一整行数据

BufferedWriter(Writer r)

newLine() 跨平台换行(window、Linux不同平台要求换行符不一致)

  1. 字节缓冲流

把基本流帮装成高级流:

BufferedInputStream( InputSteam is)

BufferedOutputStream( OutputSteam os)

  • 缓冲流自带长度为8192的缓冲区
  • 可以显著提高字节流的读写性能
  • 对于字符流提升不明显,但是为其提供特有的两个方法

转换流

属于字符流的

是字符流的字节流中间的桥梁

InputStreamReader(转换输入流)

OutputStreamWriter(转换输出流)

作用:字节流中想要使用字符流中的方法了

序列化流

高级流,用来包装普通流,属于字节流的一种,负责输出数据,与之相反的是反序列流,负责输入数据。

序列化流:objectOutputStream

反序列化流:objectInputStream

序列化流

也叫对象操作输出流

可以把Java中的对象写到本地文件中

使用方法:

  • objectOutputStream(OutputStream out) 把基本流包装成高级流
  • writeObject( object obj) 把对象序列化(写出)到文件中

反序列化流

也叫对象操作输入流

可以把序列化到本地文件中的对象,读取到程序中

使用方法:

  • objectInputStream(InputStream In) 把基本流变成高级流
  • readObject() 把序列化到本地文件中的对象,读取到程序中来

注意事项

  1. 写出时需要实现Serializable接口,不然会报错
  2. 序列化流写到文件中的数据是不能修改的,一旦修改就无法再次读回来
  3. 序列化到本地文件中对象后,不能修改实现Serializable接口类的代码,否者就会 改版本号,再进行反序列化时因为版本号不同就会出现错误
    解决方法:可以进行一个版本号的统一就不会出现该情况发生
private static final long serialVersionUID = 1L; //定义一个版本号
  1. 如果不想把对象的某个属性序列化(写)到文件中,使用瞬态关键字transient就不会序列化(写)到文件中了
private transient int age;

打印流

高级流,用来包装基本流的,打印流只能写,不能读

  • PrintStream 字节打印流
  • PrintWriter 字符打印流

特点:

  1. 打印流自能操作文件的目的地,不能操作数据源(只能写,不能读)
  2. 特有的写出方法,可以实现数据的原样写出
  3. 特有的写出方法,可以实现自动刷新、自动换行

字节打印流

创建对象:PrintStream(OutputStream/File/String ) 关联字节输出流/文件/文件路径 没有缓冲区

方法:

  1. write(int b) 常规方法,将指定字节写出
  2. println(Xxx xx) 特有方法,打印任意数据,自动换行(没有ln就不自动换行)
  3. printf(String format , Object… args) 特有方法,带有占位符的打印语句,不换行

字符打印流

字符打印流底层有缓冲区,想要自动刷新需要手动开启

创建对象:PrintWrite(Write/File/String ) 关联字节输出流/文件/文件路径

方法:

  1. write(…) 常规方法,写出字节或者字符串
  2. println(Xxx xx) 特有方法,打印任意数据,自动换行(没有ln就不自动换行)
  3. printf(String format , Object… args) 特有方法,带有占位符的打印语句,不换行

解压缩流/压缩流

  • 解压缩流
    把每一个ZipEntry按照层级拷贝到本地另一个文件中
  • 压缩流
    把每一个文件/文件夹看成ZipEntry对象放到压缩包里面

工具包

Commons - io

作用:提高IO流的开发效率

下载官网路径:Commons IO – 下载 Apache Commons IO

下载完后加压就能看见commons-io-2.11.0.jar包了

使用步骤:

  • 在项目中创建lib包
  • 将commons-io-2.11.0.jar包复制粘贴到lib包中
  • 右键点击commons-io-2.11.0.jar包,选择Add as Library ->点击OK
  • 在类中导包使用