IO流(字节流)

概念

数据传输技术,可以实现将数据在JVM和本地设备间进行传输

I:input 输入

O: output 输出

作用为实现数据传输,相当于管道

流的分类

1,从流方向上分

  • 输入流:本地设备向JVM进行传输
  • 输出流:JVM向本地设备进行传输

2,从传输单位上分

  • 字节流: 以字节为单位进行数据传输,可以传输任意类型的文件。如文本,视频,图片,音频等
  • 字符流:以字符为单位进行数据传输,只能传输文本类型的文件 

3.从传输功能上分

  • 节点流:真正的具有传输功能的流
  • 过滤流:没有传输功能的流,作用为给节点流增强传输能力或者增加附加功能

字节流涉及的API

1,InputSteam:字节输入流的抽象总父类

2,OutputStream:字节输出流的抽象总父类

3,FileInputStream:字节输入节点流

4.FileOutoutStream:字节输出节点流

输入流

创建
FileInputStream fis = new FileInputStream("要读取的文件路径");
绝对书写

1,绝对路径:以电脑磁盘为基点的完整路径

2,相对路径:以项目路径为基点的路径(文件必须在当前项目下)

注意事项

1,路径书写必须截至至文件

2,文件必须存在,不然报FileNotFound异常

常用方法

1,int  read(); 读取一个字节并返回,读取到达末尾返回-1

2.int read(byte[]); 尝试读取数组长度的数据至数组中,返回实际读取个数,读取到达末尾返回-1

3,close(); 关闭流链接,释放相关资源(所有流都具有的方法)

import java.io.FileInputStream;

public class TestFIS2 {
    public static void main(String[] args)throws Exception {
       //创建字节输入节点流对象
        FileInputStream fis = new FileInputStream("file/b.txt");
        //利用read()读取所有内容
        while (true) {
            //接收本次读取结果
            int n= fis.read();
            //判断读取是否到达末尾
            if (n == -1) {
                break;
            }
            System.out.println(n);
        }
        //利用read(byte[])读取所有内容
        while (true) {
            //创建用来接收的数组
            byte[] bs = new byte[5];
            //接收本次读取结果
            int n = fis.read(bs);
            //判断读取是否到达末尾
            if (n == -1) {
                break;
            }
            //遍历查看读取内容
            for (byte b : bs) {
                System.out.print(b+"  ");
            }
            System.out.println();
        }
        
        //关流
        fis.close();
    }
}

输出流

创建

FileOutputStream fos=new FileOutputStream("接收的文件路径",true|false);

  • true表示数据追加,false表示数据覆盖。省略时默认为false

  • 文件不存在,自动创建

    • 无法创建文件夹

常用方法

1,write(int); 向目标文件写入一个字节

2,write(byte[]); 向目标文件写入一个数组的数据

3,flush(); 强制刷新缓冲区(所有输出流都有)

import java.io.FileOutputStream;

public class TestFOS1 {
    public static void main(String[] args)throws Exception {
        //创建字节输出节点流
        //FileOutputStream fos = new FileOutputStream("file/c.txt");
        FileOutputStream fos = new FileOutputStream("file/c.txt",true);

        //写入一个字节
        fos.write(65);
        fos.write(66);
        fos.write(67);
        fos.write(68);
        //写入多个字节
        String s = "abcdefg1234567";
        //将字符串转为byte数组
        byte[] bs = s.getBytes();

        fos.write(bs);

        //关流
        fos.close();

        System.out.println("操作成功!");
    }
}


标准异常处理

try(
    需要自动关流的对象创建语句
){
}catch(){}
  • JDK7.0之后,所有的流对象都实现了AutoCloseable接口,该接口中提供了自动关流所需的close()方法

文件复制

原理:借助JVM使数据在两个文件之间传输,先将文件A的数据读取到JVM中,然后再从JVM中将数据写入到文件B,反复如此操作直至数据复制完成

先读后写

package com.by.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestCopy {
    public static void main(String[] args) {
        //copy1();
        copy2();
    }
    //一次复制一个字节
    public static void copy1(){
        try (
                //被复制到文件路径
                FileOutputStream fos=new FileOutputStream("file/text_copy1.txt");
                //被复制的文件路径
                FileInputStream fis=new FileInputStream("file/text.txt")
                ) {
            while (true) {
                //读取当前字节
                int n = fis.read();
                //判断读取是否到达末尾
                if (n == -1) {
                    break;
                }
                //将当前读取字节写入到fos
                fos.write(n);
            }
            System.out.println("文件复制成功!");

        } catch (FileNotFoundException e) {
            System.out.println("文件路径不正确");
        } catch (IOException e) {
            System.out.println("文件复制失败");
        } catch (Exception e) {
            System.out.println("未知异常");
            e.printStackTrace();
        }
    }
    //一次复制一个数组
    public static void copy2(){
        try (
                //被复制到文件路径
                FileOutputStream fos=new FileOutputStream("file/text_copy2.txt");
                //被复制的文件路径
                FileInputStream fis=new FileInputStream("file/text.txt")
        ) {
            while (true) {
                //创建用来接收的数组
                byte[] bs=new byte[1024];
                //读取
                int n = fis.read(bs);
                if (n == -1) {
                    break;
                }
                //将读取数据写入到FOS
                fos.write(bs);
            }
            System.out.println("文件复制成功!");

        } catch (FileNotFoundException e) {
            System.out.println("文件路径不正确");
        } catch (IOException e) {
            System.out.println("文件复制失败");
        } catch (Exception e) {
            System.out.println("未知异常");
            e.printStackTrace();
        }
    }
}

缓冲过滤流

输入:BufferedlnputStream

输出:BuffrerdOutputStream

创建

BufferedInputStream bis=new BufferedInputStream(fis对象);
BufferedOutputStream bos=new BufferedOutputStream(fos对象);

原理

内置数据缓冲区,在进行数据读写时,数据不会直接对接磁盘,而且对接缓冲区,最终由缓冲区一次性将数据写入磁盘,由此降低JVM与磁盘之间的传输频率,从而提高效率

//字节复制+缓冲过滤流
public static void copy(){
        try (
                //被复制到文件路径
                FileOutputStream fos=new FileOutputStream("d:/file/JDK_API_1.8_zh_CN_copy1.chw");
                //被复制的文件路径
                FileInputStream fis=new FileInputStream("d:/file/JDK_API_1.8_zh_CN.chw");
                BufferedOutputStream bos=new BufferedOutputStream(fos);
                BufferedInputStream bis=new BufferedInputStream(fis)
                ) {
            while (true) {
                //读取当前字节
                int n = bis.read();
                //判断读取是否到达末尾
                if (n == -1) {
                    break;
                }
                //将当前读取字节写入到fos
                bos.write(n);
            }
            System.out.println("文件复制成功!");

        } catch (FileNotFoundException e) {
            System.out.println("文件路径不正确");
        } catch (IOException e) {
            System.out.println("文件复制失败");
        } catch (Exception e) {
            System.out.println("未知异常");
            e.printStackTrace();
        }

    }

当使用缓冲过滤进行先写后读操作时,在写入完成后,必须刷新缓冲区将数据提前写入至目标文件,然后再进行读取

刷新缓冲区:

1,bos.flush(); 直接强刷缓冲区

2.bos.close():关流之前会自动刷新缓冲区

对象过滤流

输入:ObjectlnputStream

输出:ObjectOutputStream

附加功能;

读写基本类型

读写引用类型

读写基本类型

ois.readXxx()
oos.writeXxx(值);
注:Xxx表示的为基本类型,首字母大写,如:double  readDouble | writeDouble

使用

使用对象过滤流嵌套了缓冲区,所以在先写后读时,需要在写入完成后刷新缓冲区

为了保证数据安全,在写入数据时会通过魔数机制对其加密,在读取时再对其解密,防止写入之后的数据泄露

import java.io.*;
public class TestOIS_OOS {
    public static void main(String[] args) {
        //往当前项目下的file/a.txt中写入一个5.5,然后将其读取输出
        try (
                //创建节点流
                FileOutputStream fos = new FileOutputStream("file/a.txt");
                FileInputStream fis = new FileInputStream("file/a.txt");
                //添加对象过滤流
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                ObjectInputStream ois = new ObjectInputStream(fis)
        ) {
            //先写
            oos.writeDouble(5.5);
            System.out.println("写入成功!");
            //强刷缓冲区
            oos.flush();
            //读取
            System.out.println(ois.readDouble());
        } catch (FileNotFoundException e) {
            System.out.println("文件路径不正确");
        } catch (IOException e) {
            System.out.println("读写失败");
        } catch (Exception e) {
            System.out.println("未知异常");
            e.printStackTrace();
        }
    }
}

读写引用类型

ios: Object readObject()  读取到达末尾,抛出EOFException异常
oos: void writeObject(对象) 该方法自带缓冲区刷新,先写后读时无需手动刷新缓冲区

读写String

import java.io.*;
public class Test_String {
    public static void main(String[] args) {
        //往file/b.txt中写入一首打油诗,然后读取输出
        try (
                ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file/b.txt"));
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file/b.txt"))
        ) {
            oos.writeObject("12345");
            oos.writeObject("上山打老虎");
            oos.writeObject("老虎没打着");
            oos.writeObject("打着小松鼠");
            System.out.println("写入成功!");
            //读取
            while (true) {
                //接收本次读取结果
                try {
                    String s=(String) ois.readObject();
                    System.out.println(s);
                } catch (EOFException e) {
                    //结束循环
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            System.out.println("文件路径不正确");
        } catch (IOException e) {
            System.out.println("读写失败");
        } catch (Exception e) {
            System.out.println("未知异常");
            e.printStackTrace();
        }
    }
}

读写自定义类型

  • 类必须实现Serializable接口,意味着允许被序列化
  • 序列化:IO流拆解对象信息读取的过程
  • 反序列化:IO流组装对象信息构建对象的过程
  • 可以通过transient修饰符设定某个属性不参与序列化

访问修饰符 transient 数据类型 属性名;

public class Student implements Serializable {
    private String name;
    //防止年龄参与序列化
    private transient int age;
    private double score;
    //省略getter、setter、构造、toString
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值