Java学习day18:IO流(一篇文章知识点详解)

声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)


往期回顾 

Java学习day17:File类(一片文章搞懂重难点)-CSDN博客

Java学习day16:内部类、map集合(知识点详解)-CSDN博客

Java学习day15:Object类、set集合(知识点+例题详解)_java set集合编程题-CSDN博客

 Java学习day18:IO流

为什么会有IO流?

在以后开发中会遇到文件的上传和下载,都是需要用到IO流
咱们电脑上面所有的文件, 文档  音频 图片 视频  等都是可以进行读和写的。他们怎么读的?怎么写的? 是一下子就写到项目中了吗?

不是,是依靠流的形式进行读和写。
在读取的时候,会将上传的文件(音频 视频 等)变成流的形式 一点一点来处理的 拆解开来出来的。

1.缓冲的概念 

比如生活中:
看视频有点卡?我们会暂停一下,加载缓冲一下。
快递:送到物流中转站,然后分批次的发。物流中转站就是缓冲的概念。

IO流的本质就是对电脑的文件进行读和写的
计算机通过CPU内存读取磁盘上面的文件数据,一次读取1字节。但是可以加上缓冲的概念
每次读取4kb。效率会高点的,后面咱们可以测试一下。效率是不是确实高了。 

2.IO流的分类 

我们在用代码进行演示的时候,首先明确一个东西,所谓的内存,就是我们的Java代码!

输入流输出流是针对内存来说,参照物:是内存,就是Java代码
输入流: 从磁盘读取到内存
输出流:从内存写入到磁盘

input:   输入   从磁盘读取数据到内存
使用input输入流的应用场景是啥:比如 磁盘上面有一个1.txt文件,将1.txt文件的内容读取到Java内存中。使用的是输入流。 

2.1.从磁盘读取数据到内存(Java代码)

磁盘=>代码中    输入流input

2.1.1.字节输入流   FileInputStream

字节输入流:磁盘上面有一个1.txt文件,现在要将1.txt文件中的内容读取到内存(Java代码中)
Java给咱们封装好了类: FileInputStream  文件输入流(字节输入流)

示例:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        File file = new File("c:/aaa/1.txt");
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
        byte[] buf = new byte[1024 * 4];//缓冲区4096字节
//        int read = bis.read(buf);
//        System.out.println(read);
        int length = -1;
        while ((length = bis.read(buf)) != -1) {
            System.out.println("狗蛋");
            System.out.println(new String(buf, 0, length));
        }
        bis.close();
        fis.close();
    }
}

看着只有短短几行代码,就实现了从磁盘输入数据到内存中,但是需要知道每一行代码的原理,是怎么来的,为什么这么来!!!!!!!!!

仔细看下面的注释!!!!!

详细注释代码:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //将磁盘上面的c:/aaa/1.txt文件这个数据读取到内存(Java)中
        //加上缓冲的效果,这种很牛逼啊,将磁盘上面的东西弄到咱们Java代码中
        //1.创建File对象,是咱们本地磁盘文件的一个File对象
        //为啥要创建这个File对象?因为要读取1.txt这个文件的里面的
        //内容,首先先找到文件再说啊。
        File file = new File("c:/aaa/1.txt");
        //2.创建文件字节输入流对象,来操作1.txt
        //FileInputStream(File file)
        //通过打开与实际文件的连接创建一个 FileInputStream ,
        // 该文件由文件系统中的 File对象 file命名。
        //将c:/aaa/1.txt文件转为字节输入流的形式,之后可以按照流的形式读取到内存中
        FileInputStream fis = new FileInputStream(file);
        //3.fileInputStream 这个流不具备缓冲的效果。
        //但是加上缓冲的效果!!! 咋办?使用另外一个流
        //BufferedInputStream
        //A BufferedInputStream为另一个输入流添加了功能,即缓冲输入
        //咋加?将FileInputStream传给BufferedInputStream 此时
        //FileInputStream  就具备缓冲的功能了!!!
        BufferedInputStream bis = new BufferedInputStream(fis);
        //使用字节缓冲流操作咱们的1.txt
        //当创建BufferedInputStream时,
        // 将创建一个内部缓冲区数组,这个数组是什么数据类型的?
        //5.创建一个缓冲区的数组  byte  为啥是byte类型的数组
        //因为是字节输入流  所以是byte  byte 就是字节
        //当缓冲数组是2个字节的时候,每次读取的时候存到缓冲数组中,只存2个字节
        //发现数据一次性读取不完?咋办?咋解决?
        byte[] buf = new byte[1024 * 4];//缓冲区4096字节
        //现在数组是空的
        //6.读取数据
        //public int read(byte[] b)
        //         throws IOException
        //从输入流读取一些字节数,并将它们存储到缓冲区b 。
        // 实际读取的字节数作为整数返回
        //将1.txt文件的内容 读取到缓冲数组中  buf 里面
        //之前buf是一个空的数组,现在通过read方法将1.txt文件中的
        //内容读取到了 buf空的数组中
//        int read = bis.read(buf);
//        System.out.println(read);
        //6.调用read方法之后,buf 数组就有值了 能不能打印一下
        //借助于String类来展示byte数组的内容
        //buf  给字符串  为了展示字节数组中的内容的
        //0 偏移量   buf这个数组中从哪开始取值  从下标为0 的地方取值
        //read  取6个
        //如果b的长度为零,则不会读取字节并返回0 ;
        // 否则,尝试读取至少一个字节。
        // 如果没有字节可用,因为流在文件末尾,则返回值-1
        int length = -1;
        //如果length=-1  那么就会到达流的末尾  就证明后面没哟数据
        //循环结束,不要再读了
        while ((length = bis.read(buf)) != -1) {
            //循环4次
            System.out.println("狗蛋");
            //数组中的东西要展示出来  使用String
            //将磁盘上面的内容 读取到 =》 内存  buf
            System.out.println(new String(buf, 0, length));
        }
        //7.流是需要关闭的
        bis.close();
        fis.close();



    }
}

字节输入流是比较重要的,自己要能完全独立写出这个过程!

public class Main {

    public static void main(String[] args) throws IOException {

        //创建file对象
        File file = new File("D:/aaa/a.txt");

        //将file对象的文件内容转换为流形式,方便后续输入
        FileInputStream fis=new FileInputStream(file);

        //为了缓存功能,引入BufferedInputStream
        BufferedInputStream  bis= new BufferedInputStream(fis);

        //把读取的数据缓存到字节数组byte
        byte[] bytes = new byte[3];

        //用BufferedInputStream的read方法读取数组数据
        //int read = bis.read(bytes);
        //System.out.println(read);

        //如果缓存数组容量不够,就需要循环读取,循环的时候注意,目前win11一个中文3字节,如果拆分读取的时候以2字节拆,就会出现乱码,因为会把一个中文拆分 
        int length=-1;

        while ((length=bis.read(bytes))!=-1){
            System.out.println("666");
            System.out.println(new String(bytes,0,length));
        }

        //如果读出数据,利用String类读取数组数据
        //System.out.println(new String(bytes,0,read));

        //最后,关闭流,避免资源浪费
        bis.close();
        fis.close();
    }

 一定要好好想想这个流程是咋走的?

想象门口放了一袋大米(就是磁盘的本地文件,文件的内容),现在我要求把门口给我运到厨房(Java的内存),不能使用袋子直接搬运?

怎么解决?可以找一个杯子(就是缓冲数组)。一杯子一杯子的运。能接受不?

比如磁盘上面的380字节的数据,  咋把读取到内存中? 弄一个缓冲数组,每次读取3字节

BufferedInputStream  其实FileInputStream其实一次读取一个字节的,但是使用BufferedInputStream  了之后,可以搞一个缓冲的数组,一次可以读取多个,那么循环次数就会减少,代码的效率就会提升。循环1000遍 和循环1遍的效率 循环1遍的效率明显高很多。

所以最终总结出来,将磁盘上面的某一个文件的内容读取到内存中,就是这样:


 1、实例化一个file对象   找到本地磁盘的一个文件对象
 2、实例化一个FileInputStream  
 3、加上缓冲流 BufferedInputStream
 4、使用缓冲流对象 将内容读取read(buf)到内存缓冲数组中  使用while循环来读取
 5.关闭流 

2.1.2.字符输入流   FileReader 

思路都是一样的,只是类换成了FileReader、BufferedReader

 首先记住,字符流的底层也是字节流所以说开发中常用字节流而不是字符流.

它也是输入流,将磁盘的某一个文件读取到内存,是一个阅读字符文件的便利类,是专门处理字符文件的,比如txt文件。音频视频图片不能使用这个流。因为需要解码,编码,会出问题

是从字节流到字符流的桥:它读取字节,并使用指定的`charset`将其解码为[字符]。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
牵涉到解码,底层是字节流,但是会解码为字符。如果解码失败就意味着咱们读取失败了

字符输入流的几个常用方法,实际上是不会用的:

read(char[] cbuf)   将文件内容读取到字符数组中(缓冲区)

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //将c盘下面的aaa文件夹下面的1.txt文件的内容 读取到Java内存中
        //和字节流一模一样
        //1.新建一个File对象
        File file = new File("c:/aaa/1.txt");
        //2.新建FileReader  对象 字符输入流
        FileReader fr = new FileReader(file);
        //3.FileRFeader没有缓冲的效果,可以加上缓冲的效果
        //杂加?BufferedReader
        BufferedReader br = new BufferedReader(fr);
        //4.字节的缓冲数组 是字节
        //字符的缓冲数组  是字符
        char[] cbuf = new char[4];//缓冲区是4个字符
        //这个方法是用的!!!
        //5. read(char[] cbuf) 将文件内容读取到字符数组中(缓冲区)
        int length = -1;
        
        while ((length = br.read(cbuf)) != -1) {
            System.out.println(length);
            //6.将数组展示到控制台
            System.out.println(new String(cbuf, 0, length));
        }

        //7.关闭流
        br.close();
        fr.close();

    }
}

int read()  一次读取一个字符,返回值是字符对应的assic码值 

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //将c盘下面的aaa文件夹下面的1.txt文件的内容 读取到Java内存中
        //和字节流一模一样
        //1.新建一个File对象
        File file = new File("c:/aaa/1.txt");
        //2.新建FileReader  对象 字符输入流
        FileReader fr = new FileReader(file);
        //3.FileRFeader没有缓冲的效果,可以加上缓冲的效果
        //杂加?BufferedReader
        BufferedReader br = new BufferedReader(fr);

        //这个方法不用!!!
        //5.int read() 一次读取一个字符,返回值是字符对应的assic码值
        int length = -1;
        while ((length = br.read()) != -1) {
            System.out.println(length);

        }

        //7.关闭流
        br.close();
        fr.close();

    }
}

read(char[] cbuf, 0, length)  将文件内容读取到字符数组中(缓冲区) 

import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //将c盘下面的aaa文件夹下面的1.txt文件的内容 读取到Java内存中
        //和字节流一模一样
        //1.新建一个File对象
        File file = new File("c:/aaa/1.txt");
        //2.新建FileReader  对象 字符输入流
        FileReader fr = new FileReader(file);
        //3.FileRFeader没有缓冲的效果,可以加上缓冲的效果
        //杂加?BufferedReader
        BufferedReader br = new BufferedReader(fr);
        //4.字节的缓冲数组 是字节
        //字符的缓冲数组  是字符
        char[] cbuf = new char[4];//缓冲区是4个字符
        //这个也不用!!!
        //5. read(char[] cbuf, 0, length) 将文件内容读取到字符数组中(缓冲区)
        int length = -1;
        while ((length = br.read(cbuf, 0, 2)) != -1) {
            System.out.println(length);
            //6.将数组展示到控制台
            System.out.println(new String(cbuf, 0, length));
        }

        //7.关闭流
        br.close();
        fr.close();

    }
}

String readLine()  一次读取一行数据,r如果到达行的末尾就返回就是一个null 

import java.io.*;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //将c盘下面的aaa文件夹下面的1.txt文件的内容 读取到Java内存中
        //和字节流一模一样
        //1.新建一个File对象
        File file = new File("c:/aaa/1.txt");
        //2.新建FileReader  对象 字符输入流
        FileReader fr = new FileReader(file);
        //3.FileRFeader没有缓冲的效果,可以加上缓冲的效果
        //杂加?BufferedReader
        BufferedReader br = new BufferedReader(fr);
        //一次读取一行数据,r如果到达行的末尾就返回就是一个null
//        String s = br.readLine();
//        System.out.println(s);
//        String s1 = br.readLine();
//        System.out.println(s1);
        String str;
        //有可能会用的
        while ((str = br.readLine()) != null) {
            System.out.println(str);
        }
        //7.关闭流
        br.close();
        fr.close();

    }
}

这里可以留意一下循环是怎么写的

2.2.从内存(Java代码)写入数据到磁盘 

代码=>磁盘某一个文件    输出流output

2.2.1.字节输出流 FileOutputStream

前面字节输入流弄懂了,后面这个输出流就很简单了,主要区分几点:

1.方法名称中的Input改为了Output
2.之前用的read方法,现在用write方法
3.输出后是先刷新流,再关闭,用到flush()
4.最后关闭流,顺序不能搞反,先关闭有缓冲功能的流bos.close()

几个常用方法:

①write(byte[] b)

之前是输入,把byte数组转String,用的new String()
现在是输出,需要String类型转byte数组,用到一个方法getBytes()

示例:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //将Java代码中的一个字符串写入到咱们的磁盘的某一个文件中
        //1.创建File对象,文件路径对象  告知编译器要把数据写到哪个文件中
        File file = new File("c:/aaa/2.txt");
        //2.实例化字节输出流对象
        FileOutputStream fos = new FileOutputStream(file);
        //3.对FileOutputStream  加上缓冲的效果
        //猜测一下  FileInputStream所对应的缓冲流  BufferedInputStream
        //FileOutputStream  所对应的缓冲流  BufferedOutputStream
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //4.将一个字符串写入到磁盘中
        String str = "大家再等我一天,后天见面!!!";
        // write(byte[] b)
        //咱们的参数是字节数组,咋办?str是一个字符串 但是参数是一个字节数组,咋解决?
        //str是字符串 不能强转  将字符串转为字节数组,没有讲过!!!
        //将str字符串转为字节数组
        byte[] bytes = str.getBytes();
        bos.write(bytes);
        //5.写完以后一定要刷新流然后关闭流
        bos.flush();//没有实际的意义,可以不写的
        //6.关闭流
        //在输入流的时候一定是先开的后关,后开的先关
        bos.close();
        fos.close();
    }
}

②void write(int b)

示例:

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //将内容写入到3.txt文件中
        File file = new File("c:/aaa/3.txt");
        FileOutputStream fos = new FileOutputStream(file);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        //开始写了
        //void write(int b);
        //传参是一个int类型,但是真正写入的时候是int类型所对应的字符
        bos.write(97);//开发不用!!!
        bos.flush();
        bos.close();
        fos.close();
    }
}

③write(byte[] b,int off,int len)  把一个字节数组写一个到缓冲流  从off开始偏移  写入len个字节 

示例:

import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        File file= new File("c:/aaa/4.txt");
        FileOutputStream fos = new FileOutputStream(file);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        String str = "abcdefg";//7个字节
        //write(byte[] b,int off,int len)
        byte[] bytes = str.getBytes();
        //写一个到缓冲流  从0开始偏移  写入2个字节

        //可以借助于循环往里面写!!!
        bos.write(bytes, 0, 2);//ab
        bos.write(bytes, 2, 2);//cd
        bos.write(bytes, 4, 2);//ef
        bos.write(bytes, 6, 1);//ef
        bos.flush();
        bos.close();
        fos.close();

    }
}

由于是写入,所以不会出现被覆盖的情况。

最后,如果大家前面的知识点都弄懂了,那么实际写的时候,只需要两行代码就可以,不知道大家看得懂不?多看看。

import java.io.*;

public class Demo4 {
    public static void main(String[] args) throws IOException {

        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("c:/aaa/4.txt")));
        bos.write("xixida".getBytes());
        bos.flush();
        bos.close();

    }
}
2.2.2.字符输出流  FileWriter 

是一个 写字符文件的便利类

同样的几个方法:

①viod writer(char[] cbuf, int off, int length)

 示例:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //从内存写入数据到磁盘的文件中
        File file = new File("c:/aaa/2.txt");
        FileWriter fw = new FileWriter(file);
        //加缓冲流
        BufferedWriter bw = new BufferedWriter(fw);
        //viod writer(char[] cbuf, int off, int length);
        String str = "今天的天气真的太热了";
        //将字符串转为char数组
        char[] chars = str.toCharArray();
        //将chars数组中  从0 开始  取3个字符写入到缓冲流中
        bw.write(chars, 3, 3);
        bw.close();
        fw.close();
    }
}

② viod writer(char[] cbuf) 

示例:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //从内存写入数据到磁盘的文件中
        File file = new File("c:/aaa/2.txt");
        FileWriter fw = new FileWriter(file);
        //加缓冲流
        BufferedWriter bw = new BufferedWriter(fw);
        //viod writer(char[] cbuf);
        String str = "今天的天气真的太热了";
        //将字符串转为char数组
        char[] chars = str.toCharArray();
        //将chars数组中,直接将字符数组中的所有的数据写到缓冲流中
        bw.write(chars);
        bw.close();
        fw.close();
    }
}

注意字符串转char类型数组用了一个方法toCharArray() 

viod writer(String str)
viod writer(String str, int off, int length)
bw.newLine();//  功能代码 起到一个换行的作用 

示例:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //从内存写入数据到磁盘的文件中
        File file = new File("c:/aaa/2.txt");
        FileWriter fw = new FileWriter(file);
        //加缓冲流
        BufferedWriter bw = new BufferedWriter(fw);
        //viod writer(String str);

        String str = "对方网络不佳!!!";
        //viod writer(String str, int off, int length);
       //bw.write(str);
       //bw.write(str, 1, 4);
        bw.write("呵呵");
        bw.newLine();//写完呵呵以后换行写  功能代码 起到一个换行的作用
        bw.write("哈哈");
        bw.newLine();
        bw.write("嘻嘻");
        bw.close();
        fw.close();
    }
}

 最后写两个例题:

建议大家自己先写,最后看答案。
1.复制一本小说到另外一个盘符下面

2.复制一个图片到另外一个盘符下面

1:

import java.io.*;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(new File("c:/bbb/DiBa.txt")));
        BufferedWriter bw = new BufferedWriter(new FileWriter(new File("c:/aaa/sb1.txt")));

        int length = -1;
        char[] cbuf = new char[4 * 1024];
        while ((length = br.read(cbuf)) != -1) {
            bw.write(cbuf, 0, length);

        }
        bw.close();
        br.close();

    }
}

2:(记得不能使用字符流,因为解码,编码的时候会出问题的!!!) 

import java.io.*;

public class Demo5 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(new File("c:/aaa/3.gif")));
        BufferedWriter bw = new BufferedWriter(new FileWriter(new File("c:/bbb/333.gif")));

        int length = -1;
        char[] cbuf = new char[4 * 1024];
        while ((length = br.read(cbuf)) != -1) {
            bw.write(cbuf, 0, length);

        }
        bw.close();
        br.close();

    }
}

此时能成功复制,但是会发现打不开 

 3.总结

我们针对于字节输入流和字节输出流来写一个案例

题目:将c:/bbb文件夹下面一个视频 (源文件) 复制到c:/aaa文件夹下面

思路:将bbb文件夹下面的视频先读取到内存,然后再从内存写入磁盘aaa文件夹下面

示例:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        copyVideo1();
    }
    //现在咱们讲的这个是带有缓冲的,看看带有缓冲视频的复制的耗时多少 2610ms
    //写一个方法将bbb文件夹下面的3.map4格式的视频复制到aaa文件夹下面
    //用带缓冲的,效率高
    public static void copyVideo () throws IOException {

        //1.创建字节缓冲输入流  将磁盘的数据读取到内存
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("c:/bbb/3.mp4")));

        //2.创建字节缓冲输出流   从内存写入到的文件  源文件是mp4格式,写入到的也必须是mp4格式的
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("c:/aaa/goudan.mp4")));

        //3.准备一个字节数组 缓冲区数组
        byte[] buf = new byte[4 * 1024];//代码走到这一步是空的
        //4.从磁盘读取数据到内存
        int length = -1;
        //这个视频很大,依靠循环来读取,每次读4 * 1024字节
        while ((length = bis.read(buf)) != -1) {//从磁盘上读取数据到buf缓冲数组中
            //每次循环 buf数组中有值,顺便依靠循环写入到磁盘
            System.out.println("qwer");
            bos.write(buf, 0, length);
        }
        //5.关闭流
        bos.close();
        bis.close();
    }
    
}

分析:

缓冲数组  byte[] buf = new byte[4];
视频由字节组成的 一次读取 4096字节  直到最后一次 不一定4096字节
最后一次3456  字节   write(buf, 0, 3456),所以必须要用这个write方法
相当与将所有字节重新拼接了一下
读取的时候每次读取4096个放到咱们的缓冲数组中,然后立马写入另外磁盘文件下面
直到读取完,写入完即可,如果多了或者少了,视频最后都是无法播放的 

qwertyuiopasd  13字节

//第一循环
while ((length=bis.read(buf)) != -1) {//buf 里面 有 qwer
 bos.write(buf, 0, 4);  文本里面有  qwer
}
第二次循环
while ((length=bis.read(buf)) != -1) {//buf 里面 有 tyui
 bos.write(buf, 0, 4);  文本里面有  qwertyui
}
第三次循环
while ((length=bis.read(buf)) != -1) {//buf 里面 有 opas
 bos.write(buf, 0, 4);  文本里面有  qwertyuiopas
}
第四次循环
while ((length=bis.read(buf)) != -1) {//buf 里面 有 d
 bos.write(buf, 0, 1);  文本里面有  qwertyuiopasd
}

同时我们对比一下有缓冲数组和没有的,效率差别很明显。

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        copyVideo1();
    }
    //现在咱们讲的这个是带有缓冲的,看看带有缓冲视频的复制的耗时多少 2610ms
    //写一个方法将bbb文件夹下面的3.map4格式的视频复制到aaa文件夹下面
    //用带缓冲的,效率高
    public static void copyVideo () throws IOException {
        //获取系统的当前的毫秒数
        long start = System.currentTimeMillis();
        //1.创建字节缓冲输入流  将磁盘的数据读取到内存
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("c:/bbb/3.mp4")));

        //2.创建字节缓冲输出流   从内存写入到的文件  源文件是mp4格式,写入到的也必须是mp4格式的
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("c:/aaa/goudan.mp4")));

        //3.准备一个字节数组 缓冲区数组
        byte[] buf = new byte[4 * 1024];//代码走到这一步是空的
        //4.从磁盘读取数据到内存
        int length = -1;
        //这个视频很大,依靠循环来读取,每次读4 * 1024字节
        while ((length = bis.read(buf)) != -1) {//从磁盘上读取数据到buf缓冲数组中
            //每次循环 buf数组中有值,顺便依靠循环写入到磁盘
            System.out.println("qwer");
            bos.write(buf, 0, length);

        }
        //5.关闭流
        bos.close();
        bis.close();
        //复制完以后再得到一个毫秒数,相减 就得到复制一个视频需要的时间
        long end = System.currentTimeMillis();
        System.out.println(end - start);


    }
    //下面来=看一下不带缓冲的流的读写
    public static void copyVideo1 () throws IOException {
        long start = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream(new File("c:/bbb/3.mp4"));
        FileOutputStream fos = new FileOutputStream(new File("c:/aaa/goudan.mp4"));
        int length = -1;
        while ((length = fis.read()) != -1) {
            fos.write(length);
        }
        fos.close();
        fis.close();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

当然缓冲数组也不是越大越好,大了占内存。 

字节流:  可以处理 文本  图片 音频  视频
字符流: 只能处理文本 

综上所述:开发中用字节流 。


以上,就是今天的所有知识点了。IO流是java知识点中一个非常重要的核心,大家得多花点时间,静下心看代码,写代码,多理解。

加油吧,预祝大家变得更强!

你可能感兴趣的:(java从0到1,学习,java,intellij-idea,java-ee,开发语言)