Java~IO流概述、分类、常用的流总结(FileInputStream&FileOutputStream、缓冲流、数据流、标准流、对象流)

IO流概述
  • 什么是IO流
    I:input
    O:output
    通过IO就可以完成硬盘文件的读和写
    硬盘中的文件加载到内存就是输入(Input)、
    内存将使用或者修改过的文件再返回给硬盘就是输出(Output)
  • IO流分类?
    有两种划分方式,一种是按照流的方向进行划分:
    输入流:以内存为参照物,往内存中去,叫输入(Input),或者叫做读(Read
    输出流:以内存为参照物,从内存中出,叫输出(Output),或者叫做写(Write
    另一种方式是按照字符读取数据方式的不同进行分类:
    字节流:按照字节的方式读取数据,一次读取1个字节byte
    就是一次读取8个二进制,这种流非常万能,能读取任何类型的文件.包括:文本文件,图片,声音文件等…
    字符流:按照字符方式进行读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取.

Java是站在了前人的肩膀上向前眺望.更多的是应用层面的,对底层的东西了解的不多.可能C++多一些

Java中提供了哪些流?每个流的特点是什么?每个流对象上的常用方法有哪些??

  • java IO流的四大家族
    四个家族首领:
    java.io.InputStream 字节输入流
    java.io.OutputStream 字节输出流
    java.io.Reader 字符输入流
    java.io.Writer 字符输出流
    以Stream结尾都是字节流,以Reader/Wrider结尾都是字符流.
    这四个首领全是抽象类(abstract class)
  • 所有流都实现了java.io.Closeable接口,都是可关闭的.
    都有close方法
    流就像是内存和硬盘之间的管道,用完之后一定要关闭,不然会耗费(占用)很多的资源.用完流之后一定要关闭
  • 所有的输出流都实现了java.io.Flushable接口,都是可刷新的,都有flush()方法.
    输出流在最终输出之后,必须刷新一下。
    这个刷新就是将通道/管道当中剩余未输出的数据强行输出完(清空管道)
    如果没有flush()可能会导致丢失数据。
  • java.io包下需要掌握的16个流总结(部分了解即可)
    文件专属:
    java.io.FileInputStream(重点
    java.io.FileOutputStream(重点
    java.io.FileReader
    java.io.FileWriter
    转换流:(将字节流转换成字符流)
    java.io.InputStreamReader
    java.io.OutputStreamWriter
    缓冲流专属:
    java.io.BufferedReader
    java.io.BufferedWriter
    java.io.BufferedInputStream
    java.io.BufferedOutputStream
    数据流专属:
    java.io.DataInputStream
    java.io.DataOutputStream
    标准输出流:
    java.io.PrintWriter
    java.io.PrintStream (重点
    对象专属流:
    java.io.ObjectInputStream (重点
    java.io.ObjectOutputStream (重点
利用FileInputStream读取文件
  • FileInputStream是文件字节输入流,万能,任何类型的文件都可以采用这个流来读
  • 字节的方式,完成输入操作,完成读取操作(硬盘–>文件)

逐个字节读取

public static void main(String[] args)throws Exception{
            FileInputStream file = new FileInputStream("C:\\Test\\temp");
            int readData=file.read();
            System.out.println(readData);//第一次读取到第一个字节
            readData=file.read();
            System.out.println(readData);//第二次读取到第二个字节
            readData=file.read();
            System.out.println(readData);//没有内容会读取到-1
        }

直接将异常在main方法中抛出非常不规范,一般是try catch,如下面

    public static void main(String[] args){
        //如果在main方法中有编译异常,一般会try catch 不会throws抛出
        //创建文件字节输入流对象
        FileInputStream file= null;//文件路径在写入时,IDEA会自动把\变成\\
        try {
            file = new FileInputStream("C:\\Test\\temp");//我们在temp文件中提前写入内容:两个字母ab
            //开始读取数据
            int readData=file.read();//这个方法的返回值是:读取到的“字节”本身
            System.out.println(readData);
            readData=file.read();
            System.out.println(readData);
            //当读取到文件的末尾时,没有数据了会返回-1 继续读 还是返回-1
            readData=file.read();
            System.out.println(readData);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e){
         e.printStackTrace();
        }finally{
            //在finally语句块中确保流一定关闭
            if (file != null) {
                //关闭流的前提是,流不是空,流是null没必要关闭
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

用循环逐个读

  public static void main(String[] args) throws Exception {
        FileInputStream file=new FileInputStream("C:\\Test\\temp");
        int readData=0;
        while((readData=file.read())!=-1){
            System.out.println(readData);
        }
        file.close();
    }

一次读取N个字节

   public static void main(String[] args)throws Exception{
        //IDEA的默认当前路径是Project这个工程的根目录
        //从根目录开始,如果文件放在IDEA中,每一层都是说在哪
        //比如我在untitled这个工程的src包的main包下的resources中放了一个文件,
        // 那么这个文件的相对路径就是..\\untitled\src\main\resources\xxx文件
        FileInputStream file=new FileInputStream("..\\untitled\\src\\main\\resources\\tempd");
        byte[] bytes=new byte[4];
        //用字节数组读,一次读取n个字节,n是数组长度
        int readCount=file.read(bytes);//方法返回值是:读取到的字节数量(不是字节本身)
        //如果文件只有5个字节,而数组长度是6 那么读取的时候只能读取到5个,所以会返回5个
        //如果文件有6个字节,分别a,b,c,d,e,f 数组长度是4 第一读会读取到4个字节,是a,b,c,d ,返回4 第二次读会读取到两个字节,并且会覆盖已经读取的字节,数组中变成
        // e,f,c,d 返回2   再次读取 文件中没有字节了,会返回-1
        System.out.println(readCount);
        System.out.println(new String(bytes,0,readCount));
        readCount=file.read(bytes);
        System.out.println(readCount);
        System.out.println(new String(bytes,0,readCount));
        file.close();
    }

FileInputStream主流用法

  public static void main(String[] args) throws Exception{
        FileInputStream file=new FileInputStream("..\\untitled\\src\\main\\resources\\tempd");
        byte[] bytes=new byte[4];
        int readCount=0;
        while((readCount=file.read(bytes))!=-1){
        //把数组转换成字符串,读多少个,转换多少个。
            System.out.println(new String(bytes,0,readCount));
        }
        file.close();
    }
FileInputStream类中其他常用方法
  • int available():返回流当中剩余的没有读取到的字节数量
 public static void main(String[] args) throws Exception{
        FileInputStream file=new FileInputStream("..\\untitled\\src\\main\\resources\\tempd");
        int readData=file.read();
        System.out.println("还剩多少个字节没有读:"+file.available());
        file.close();
    }

还剩多少个字节没有读:4

这个方法一般用来查看文件总字节数量,然后将这个数量设置为数组长度,便于一次读取文件。但是只适合比较小的文件,因为数组长度不能太大

   public static void main(String[] args) throws Exception{
        FileInputStream file=new FileInputStream("..\\untitled\\src\\main\\resources\\tempd");
        System.out.println("总字节数量:"+file.available());
        byte[] bytes=new byte[file.available()];
        int readCount=file.read(bytes);
        System.out.println(new String(bytes));
        file.close();
    }
总字节数量:5
abcde
  • long skip(long n):跳过N个字节不读
 public static void main(String[] args) throws Exception {
        FileInputStream file=new FileInputStream("..\\untitled\\src\\main\\resources\\tempd");
        file.skip(2);
        System.out.println(file.read());
    }
文件内容是abcde,跳过两个是c 而c的ASCII码值是99 所以返回99
返回:99 
利用FileOutputStream写入文件
  • FileOutputStream是文件字节输出流,负责写文件
  • 从内存到硬盘,如果文件不存在会自动建立
  • 每次写完需要刷新一下,用flush方法

两种创建方法

 //如果myfile不存在,会自动建立。如果myfile已经存在,会清空这个文件,然后重新写入
FileOutputStream file=new FileOutputStream("myfile");

 //不清空源文件,以追加的方式写入,末尾加个true
 FileOutputStream fos=new FileOutputStream("myfile",true);        

用write方法写入

   public static void main01(String[] args) throws Exception{
        FileOutputStream file=new FileOutputStream("myfile");//写文件具体在哪个位置,不写默认项目根目录
        //开始写
        byte[] bytes={97,98,99,100};
        //将整个数组全部写出
        file.write(bytes);
        //向文件中写入数组的的一部分
        file.write(bytes,0,2);
        file.flush();
    }
利用流完成文件复制
  • 一个盘中的文件要复制到另一个盘,需要先经过内存
  • 先将文件读取到内存,然后从内存输入到另一个盘中
  • 一边读、一边写

使用FileInputStream+FileOutputStream完成文件的拷贝,这个对文件的拷贝比较万能,类型没有限制,什么文件都可以

    public static void main(String[] args) throws Exception {
        FileInputStream file=new FileInputStream("C:\\Test\\temp");
        FileOutputStream fos=new FileOutputStream("C:\\Test\\afile");
 
        byte[] bytes=new byte[1024*1024];//每次最多复制1MB
        int readCount=0;
        while((readCount=file.read(bytes))!=-1){
            fos.write(bytes,0,readCount);
        }
        fos.flush();
        file.close();
        fos.close();
    }
FileReader、FileWriter的使用
  • FileReader、FileWriter也是读取文件的输入输入流,只不过按照字符来进行读取.
  • 使用方式和字节流大同小异,字节流读取n个字节时用byte数组,而字符流读取n个字符时用char数组
  //以字符方式进行读取,读取文本内容比较方便
    public static void main(String[] args) throws Exception{
        FileReader reader=new FileReader("C:\\Test\\temp");
        //开始读
        char[] chars=new char[4];
        int readCount=0;
        while((readCount=reader.read(chars))!=-1){
            System.out.println(new String(chars,0,readCount));
        }
        reader.close();
    }
  • FileWriter文件输出流,用来写文件
  • 只能写普通文本,图片、声音、视频等等都不可以
  • 能用记事本进行编辑的都是普通文本文件,和后缀无关,不一定非得是.txt
   //以字符方式进行读取,读取文本内容比较方便
    public static void main(String[] args)throws Exception{
     FileWriter file=new FileWriter("C:\\Test\\temp",true);
     char[] chars={'a','b','k','9'};
     file.write(chars);//写入这个数组的全部
     file.write(chars,0,3);//写入数组的部分
     file.write("直接写入字符串");
     file.close();
    }
自带缓冲区的字符流使用
  • 自带缓冲意思是读写文件的时候不需要再用char或者byte数组

BufferedReader

  • readLine()方法读取一行文本,但是不带换行符,读取不到内容时会返回null
  • 构造时,需要传入一个字符流
 public static void main(String[] args) throws Exception{
        FileReader reader=new FileReader("C:\\Test\\temp");
        /*当一个流里面有另一个流的时候,里面的流叫节点流,外面的流叫包装流/处理流
        当前这个程序里,FileReader就是一个节点流。BufferedReader就是包装流
        */
        BufferedReader br=new BufferedReader(reader);
        /*String line=br.readLine();
        System.out.println(line);
        line=br.readLine();
        System.out.println(line);*/ //一次读一行太慢,可以用循环
        String s=null;
        while((s=br.readLine())!=null){
            System.out.println(s);
        }
        //关闭流
        //对于多个流包装在一起,只需要关闭最外面的流就可以,里面的节点流会自动关闭
        br.close();
    }
  • 缓冲流构造时,只能传入字符流.如果想要传入字节流必须用转换流进行转换
   public static void main(String[] args)throws Exception {
        //用字节流读取文件
        FileInputStream in=new FileInputStream("C:\\Test\\temp");
        //用转换流将字节流转换成字符流
        InputStreamReader reader=new InputStreamReader(in);
        //缓冲流的构造方法要求只能传入字符流,不能传入字节流
        //reader是节点流,br包装流
        BufferedReader br=new BufferedReader(reader);
        
        //合并写法
        BufferedReader bs=new BufferedReader(new InputStreamReader(new FileInputStream("C:\\Test\\temp")));
        String s=null;
        while((s=br.readLine())!=null){
            System.out.println(s);
        }
        br.close();
        bs.close();
    }

BufferedWriter

  • 构造时同样需要传入字符流
  • 写文件完成后需要清理管道,调用flush方法
  • 写入文件时,会默认清空文件,如果不想清空,构造时设置true
   public static void main(String[] args) throws Exception{
        //带有缓冲区的字符输出流
        BufferedWriter out=new BufferedWriter(new FileWriter("C:\\Test\\temp",true));
        //开始写
        out.write("String String ");
        out.write("\n");
        out.write("helllo world");
        out.write("写文件完成后需要调用刷新方法");
        //刷新
        out.flush();
        //关闭最外层
        out.close();
    }
数据专属流了解

DataOutputStream

  • 可以将数据和数据类型一并写入文件
  • 这个文件不是普通文本文件,记事本打不开
  • 可以看成是一种加密规则,写入的文件只能用DataInputStream才能打开,还需要知道数据写入规则
 public static void main(String[] args) throws Exception{
        //数据专属的字节输出流  构造时需要传入字节流
        DataOutputStream dos=new DataOutputStream(new FileOutputStream("data"));
        //写数据
        byte b=100;
        short s=200;
        int i=300;
        long l=400L;
        float f=3.0F;
        double d=3.14;
        boolean flg=false;
        char c='a';
        //数据写入
        dos.writeByte(b);
        dos.writeShort(s);
        dos.writeInt(i);
        dos.writeLong(l);
        dos.writeFloat(f);
        dos.writeDouble(d);
        dos.writeBoolean(flg);
        dos.writeChar(c);
        //刷新
       dos.flush();
        //关闭资源
        dos.close();
    }

DataInputStream

 public static void main(String[] args) throws Exception{
       DataInputStream dis=new DataInputStream(new FileInputStream("data"));
       //开始读
        byte b=dis.readByte();
        short s=dis.readShort();
        int i=dis.readInt();
        long l=dis.readLong();
        float f=dis.readFloat();
        double d=dis.readDouble();
        boolean flg=dis.readBoolean();
        char c=dis.readChar();
        //随意输出
        System.out.println(b);
        System.out.println(s);
        System.out.println(i+1000);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(flg);
        System.out.println(c);
        dis.close();
    }
标准输入流PrintStream使用
  • 默认输出到控制台
  • 标准输出流不需要手动关闭
  • 可以改变输出方向,比如不再输出到控制台,而是输出到一个日志文件中
public static void main(String[] args) throws Exception{
        //联合起来写
        System.out.println("hello");

        //分开写
        PrintStream ps=System.out;
        ps.println("345");
        ps.println("234");
        ps.println("789");
        //对于标准输出流,不需要手动close关闭
        PrintStream printStream=new PrintStream(new FileOutputStream("log"));
        System.setOut(printStream);
        //再输出
        System.out.println("hello world");
    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值