流的概念/分类/常用流/FileInputStream+FileOutputStream实现(重点)/文件复制

流的概念/分类/常用流/FileInputStream+FileOutputStream实现(重点)/文件复制

流的概念

“流”是一个抽象的概念,它是对输入输出设备的一种抽象理解,在java中,对数据的输入输出操作都是以“流”的方式进行的。

I:Input
O:Output
通过IO可以完成硬盘文件的读和写

流的close()和flush()

close: 所有的流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法。流毕竟是一个管道,这个是内存和硬盘之间的管道,用完之后一定要关闭,不然会耗费(占用)很多资源

flush: 所有的输出流 都实现了 java.io.Flushable接口,都是可刷新的,都有flush()方法。在输出流最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道的作用就是清空管道。
注:如果没有flush()可能会导致丢失数据

io流的分类,以及各个流的特点

按照流的方向进行分类:以内存作为参照物

  • ​ **输入流:**从内存中进去,叫做输入(Input),或者叫做读(Read)
  • ​ **输出流:**从内存中出来,叫做输出(Output),或者叫做写(Write)

按照读取数据的方式不同进行分类:

字节流(万能流): 按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。这种流是万能的,什么类型的文件(文本文件,图片,声音文件,视频文件等等)都可以读取。( char 在java中是两个字节,windows操作系统中文件的a字符占用的是1个字节)

字符流: 按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取 普通文本文件(.txt) 而存在,只能读取纯文本文件。不能读取:图片,声音,word文件(存在格式,不属于普通文档/纯文本),视频等文件,

在java中只要“类名”以stream结尾的都是字节流,以“Reader/Writer结尾的都是字符流”

常用的流(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

java.io.FileInputStream实现(重点)

先在D盘创建了一个txt文件,输入内容如下:

在这里插入图片描述

int read(byte b)

读取方式 int read(byte b),一个一个字节的读,硬盘和内存的交互大,时间/资源消耗大——>不常用

/*
java.io.FileInputStream:
    1.文件字节输入流(万能流),任何类型文件都可以采用这个流来读
    2.字节的方式,完成输入的操作,完成读的操作(硬盘--->内存)
 */
	public static void main(String[] args) {
        FileInputStream fis = null;
        //创建文件字节输入流对象
        //java.io.FileInputStream(string name),
        //name为文件路径
        /*文件路径中'\'要转换成'\\',因为'\'在java中表示转义
        以下路径采用了:绝对路径的方式
        "D:\\temp.txt"
        所以,写成这个/也是可以的*/
        //注意:在IDEA中默认的当前路径 是project的根
        try {
            fis = new FileInputStream("D:\\temp.txt");

            //开始读
            int readData = fis.read();
            //这个方法的返回值是:读取到的“字节”本身
            System.out.println(readData);//a-->97

            int readData02 = fis.read();
            System.out.println(readData02);//b-->98

            int readData03 = fis.read();
            System.out.println(readData03);//c-->99

            int readData04 = fis.read();
            System.out.println(readData04);//d-->100

            int readData05 = fis.read();
            System.out.println(readData05);
            /*当读到文件末尾,再继续读,
            读取不到任何数据,
            就会返回-1
            */

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }//编译异常,需要捕捉异常

        catch (IOException e) {
            e.printStackTrace();
        }

        finally {
            //finally语句块中确保流一定关闭
            //fis.close直接调用会爆红,
            //需要在try/catch外给fis赋值为空
            if(fis != null){//避免空指针异常
                //关闭流的前提:流不是空
                //流是null的时候没必要关闭
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

在这里插入图片描述

int read(byte[] b)

读取方式 int read(byte[] b),采用byte数组,一次读取多个字节。最多读取“数组。length”个字节,减少硬盘和内存的交互,提高程序的执行效率——>常用/掌握

/*
int read(byte[] b)
一次最多读取b.length个字节
    减少硬盘和内存的交互,提高程序的执行效率
    往byte[]数组当中读
 */
public class FileInputStreamTest01 {

    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:\\temp.txt");

            //开始读,采用byte数组,一次读取多个字节。
            //最多读取“数组。length”个字节
            byte[] bytes = new byte[3];
            //准备一个长度为3的byte数组,一次最多读3个字节
            int readCount = fis.read(bytes);
            //返回值是读到的字节数-->3
            System.out.println(readCount);//abc

            readCount = fis.read(bytes);
            //返回值是读到的字节数-->1,覆盖之前的
            System.out.println(readCount);//dbc

            readCount = fis.read(bytes);
            //一个字节数都读不到,就返回-1
            System.out.println(readCount);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        catch (IOException e) {
            e.printStackTrace();
        }

        finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

在这里插入图片描述

int available()——返回流中剩余的没有读到的字节数量

可以获得总字节数量,就不需要循环,可以一次直接一次读完

注:不适合大文件,因为byte数组不能太大,几十万个应该问题不大

 byte[] bytes = new byte[fis.available()];

long skip(long n):——跳过几个字节不读

		 fis.skip(3);
         System.out.println(fis.read());
         //输出第四个字节本身-->d的ascii码值100

在这里插入图片描述

java.io.FileOutputStream实现(重点)

    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            //temp02文件不存在的时候会自动新建
             /*
            fos = new FileOutputStream("D:\\temp02.txt");
            //temp02文件不存在的时候会自动新建
            
            fos = new FileOutputStream("D:\\temp.txt");
            已经存在的文件,会先清空原文件,再写入
            */
            fos = new FileOutputStream("D:\\temp.txt",true);
            //以追加的方式在文件末尾写入,不会清空原文件内容
            //开始写
            byte[] bytes = {97,98,99,100};
            //讲byte数组全部写出
            fos.write(bytes);

            //写完后,最后一定要要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

文件复制

/*
使用FileInputStream+FileOutputStream完成文件的拷贝
拷贝过程应该是一边读,一边写
使用以上的字节流拷贝文件的时候,文件类型随意(万能流),都能拷贝
 */
public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            //创建一个输入流对象
            fis = new FileInputStream("D:\\a.txt");
            //创建一个输出流对象
            fos = new FileOutputStream("D:\\copy.txt");

            //一边读一边写
            byte[] bytes = new byte[fis.available()];
            int readCount = 0;
            while((readCount = fis.read(bytes)) != -1){
                fos.write(bytes,0,readCount);
            }

            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            //分开try,防止其中一个出现异常,影响另一个流的关闭
            if(fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
posted @ 2021-01-21 01:00  许君  阅读(196)  评论(0编辑  收藏  举报