01.14_学习Java的day23(详解)

练习题:

1、列出某个目录的所有下一级,如果它的下一级仍然是目录,再列出下一级的下一级,依次类推

2、求出某个目录的总大小
length()只能得到文件的大小。目录的大小无法直接用它得到。
目录的总大小:把它的下一级的大小累加起来就是它的总大小

3、删除一个非空目录
delete()只能删除文件或空目录
非空目录的删除:把它的下一级先请空,然后删除自己。

public class TestDigui {
    @Test
    public void test01(){
        File dir = new File("D:\\尚硅谷_191213Java班_柴林燕_JavaSE");

        listAllSubs(dir);
    }
    /*
    第一次调用listAllSubs()时,f代表的是D:\\尚硅谷_191213Java班_柴林燕_JavaSE
            File[] files = f.listFiles(); 得到的是
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\API
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\english_words
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\libs
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\ppt
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\resources
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\software
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\预习笔记
                    D:\尚硅谷_191213Java班_柴林燕_JavaSE\预装软件
            for (File sub : files) {
                System.out.println(sub);
            }
            每一次循环,sub依次代表一个

      第二次调用:   listAllSubs(),f可能代表     D:\尚硅谷_191213Java班_柴林燕_JavaSE\API
               File[] files = f.listFiles(); 得到的是
               Java Platform SE 8.chm
               JAVA_API_1.8_CHS.CHM
               ....
            for (File sub : files) {
                System.out.println(sub);
            }
            每一次循环,sub依次代表一个
          ....
     */

    public void listAllSubs(File f){
        //如果f是目录,就要获取f的下一级
        if(f.isDirectory()){
            File[] files = f.listFiles();
            for (File sub : files) {
                listAllSubs(sub);
            }
        }
        System.out.println(f);
    }

    @Test
    public void test02(){
        File dir = new File("D:\\尚硅谷_191213Java班_柴林燕_JavaSE");

        long directorySize = getDirectorySize(dir);
        System.out.println(dir + "的大小是:" + directorySize + "字节");//2,102,328,630 字节
    }

    public long getDirectorySize(File f){
        if(f.isDirectory()){
            //f是目录,把它的下一级的大小累加起来就是f的总大小
            //(1)得到f的下一级
            File[] files = f.listFiles();
            long sum = 0;
            for (File sub : files) {
//                sum += sub.length();//错误的,因为sub可能是文件,也可能是目录
                sum += getDirectorySize(sub);
            }
            return sum;
        }
        return f.length();
    }

    @Test
    public void test03(){
//        File dir = new File("d:/尚硅谷_191213Java班_柴林燕_JavaSE - 副本");
        File dir = new File("d:/img");

        forceDeleteDir(dir);
    }

    public void forceDeleteDir(File f){
        //如果f是非空目录,先删除非空目录的下一级
        if(f.isDirectory()){
            //(1)获取f的下一级
            File[] files = f.listFiles();
            //(2)遍历files,挨个儿删除下一级
            for (File sub : files) {
                //调用forceDeleteDir删除每一个下一级
                forceDeleteDir(sub);
            }
            //(3)经过上面的代码f,不管是空目录还是非空目录,现在都变成空目录
        }

        //如果f是文件,或空目录
        f.delete();
    }

}

4、目录的遍历
(1)String[] list():列出目录的所有子目录或文件的名称,包括隐藏的文件和目录
(2)File[] listFiles():列出目录的所有子目录或文件的路径名,包括隐藏的文件和目录
(3)File[] listFiles(FileFilter filter) :可以过滤不满足条件的目录或文件
(4)File[] listFiles(FilenameFilter filter)

public class TestDirectoryList {
    @Test
    public void test04() {
        File dir = new File("d:/");
        File[] list = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //pathname就是代表dir目录的下一级的子目录名或文件名
                //当目录中的子目录或文件满足条件时,就返回true,表示保留这个子目录或文件
                return pathname.isFile() && pathname.getName().endsWith(".java");
            }
        });//匿名内部类实现FileFilter接口
        for (File s : list) {
            System.out.println(s );
        }
        //d:\Hello.java
    }

    @Test
    public void test03() {
        File dir = new File("d:/");
        File[] list = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //pathname就是代表dir目录的下一级的子目录名或文件名
                //当目录中的子目录或文件满足条件时,就返回true,表示保留这个子目录或文件
                return pathname.isFile();
            }
        });//匿名内部类实现FileFilter接口
        for (File s : list) {
            System.out.println(s );
        }
        /*
        d:\Hello.java
        d:\hello.txt
        d:\pagefile.sys
         */
    }

       @Test
    public void test02() {
        File dir = new File("d:/");
        File[] list = dir.listFiles();
        for (File s : list) {
            System.out.println(s + "是文件吗?" + s.isFile());
        }
    }
 /*   @Test
    public void test02() {
        File dir = new File("d:/");
        String[] list = dir.list();
        for (String s : list) {
            System.out.println(s + "是文件吗?" + s.isFile());//s是String类型
        }
    }*/

    @Test
    public void test(){
        File dir  = new File("d:/");
        String[] list = dir.list();
        for (String s : list) {
            System.out.println(s);
        }
        /*
        $RECYCLE.BIN
        1213
        atguigu
        hello.txt
        LocalRepository
        pagefile.sys
        prepare
        ProgramFiles
        ProgramFiles (x86)
        QMDownload
        software
        System Volume Information
        work
        尚硅谷_191213Java班_柴林燕_JavaSE
        尚硅谷_191213Java班_柴林燕_MySQL_JDBC
         */
    }
}

集合章的重要性:*****
IO整章的重要性:***
为什么没那么重要?后期开发都把它这张的API给再次封装了,封装到各种工具包里了。
面试题中出现的频率没有集合等章节高,主要集中在:编码解码IO流,对象序列化IO流。

一、java.io.File类

1、File类:文件和目录路径名的抽象表示形式。

解读:(1)File类的对象,是代表一个文件或者是目录(文件夹)。
当然这个文件或目录可能在硬盘中是存在的,也可能是不存在的。但是这个对象在内存中是存在的。
(2)如何表示一个文件或目录,不管它是否存在呢?
使用文件或目录的路径名来表示。
例如:d:/1.txt d:/atguigu

2、常用的API

(1)getName():获取文件或目录名 不管文件或目录是否存在都可以获取,因为在new File对象是我们已经指定了。

以下这些属性,当文件/目录不存在时,都是默认值,如果文件或目录存在,就取真实的值
(2)long length():获取文件的大小,单位是字节 不能获取目录的的大小
(3)long lastModified():获取文件或目录的最后修改时间,单位是毫秒
(4)boolean isFile():是否是文件
(5)boolean isDirectory():是否是目录
(6)boolean canRead():是否可读
(7)boolean canWrite():是否可写
(8)boolean isHidden():是否隐藏
(9)boolean exists():是否存在

(10)路径问题
A:构造路径:在你new File对象时指定的路径,就是构造路径,和这个文件或目录是否存在无关
B:绝对路径:
从根目录开始导航就是绝对路径
C:相对路径:相对于当前项目/模块开始导航的路径
例如:D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code
D:规范路径:会把路径中类似于:…或.或/开头等路径进行解析
…:代表上一级
/开头:代表根目录,这个在web开发,或者linux,mac IOS中的/都是代表根目录
.:代表当前目录

结论:构造路径:在你new File对象时指定的路径,就是构造路径,和这个文件或目录是否存在无关
绝对路径:一定是从根目录开始导航的,如果你new对象时传入的是相对路径,那么就会从项目根目录开始导航。
规范路径:如果你new File对象时,指定的就是规范路径,那么它和绝对路径一样,
如果你new File对象时,指定的是非规范路径,那么会对…等进行解析

public class TestFile {


    @Test
    public void test06() throws IOException {
        //Java中\是需要转义的
        File file = new File("..\\..\\..\\Download\\2.txt");//相对路径:并没有从根目录开始,从任意一级目录开始
        System.out.println("文件的路径信息,构造路径:" + file.getPath());//..\..\..\Download\2.txt
        System.out.println("绝对路径:" + file.getAbsolutePath());//D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code\..\..\..\Download\2.txt
        System.out.println("规范路径:" + file.getCanonicalPath());//D:\atguigu\javaee\JavaSE20191213\Download\2.txt
    }

    @Test
    public void test05() throws IOException {
        //Java中\是需要转义的
        File file = new File("Download\\2.txt");//相对路径:并没有从根目录开始,从任意一级目录开始
        System.out.println("文件的路径信息,构造路径:" + file.getPath());//Download\2.txt
        System.out.println("绝对路径:" + file.getAbsolutePath());//D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code\Download\2.txt
        System.out.println("规范路径:" + file.getCanonicalPath());//D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code\Download\2.txt
    }

    @Test
    public void test04() throws IOException {
        //Java中\是需要转义的
        File file = new File("D:\\QMDownload\\Download\\2.txt");//绝对路径:从根目录开始一直往下导航到对应的文件夹或目录
        System.out.println("文件的路径信息,构造路径:" + file.getPath());//D:\QMDownload\Download\2.txt
        System.out.println("绝对路径:" + file.getAbsolutePath());//D:\QMDownload\Download\2.txt
        System.out.println("规范路径:" + file.getCanonicalPath());//D:\QMDownload\Download\2.txt
    }


    @Test
    public void test03(){
        //表示D盘下atguigu文件夹
        File dir = new File("d:/atguigu");
        System.out.println("atguigu文件夹的大小:" + dir.length());
    }
    @Test
    public void test02(){
        //表示D盘下1.txt文件
        File file = new File("d:/1.txt");//这个文件不存在,不影响我new对象
        System.out.println("文件的名称:" + file.getName());
        System.out.println("文件的大小:" + file.length());
        /*
        和大小/长度有关:数组的大小/长度:数组.length属性
                        字符串的长度:字符串.length();
                        集合的大小:集合.size()
                        文件的大小:文件.length()
         */
        System.out.println("最后修改时间:" + file.lastModified());
        System.out.println("file是代表一个文件吗?" + file.isFile());
        System.out.println("file是代表一个目录吗?" + file.isDirectory());
        System.out.println("文件可读吗:" +  file.canRead());
        System.out.println("文件可写吗:" +  file.canWrite());
        System.out.println("是隐藏文件吗?" + file.isHidden());
        System.out.println("文件存在码?" + file.exists());
        /*
        当文件不存在时:
        文件的名称:1.txt
        文件的大小:0
        最后修改时间:0
        file是代表一个文件吗?false
        file是代表一个目录吗?false
        文件可读吗:false
        文件可写吗:false
        是隐藏文件吗?false
        文件存在码?false

        当文件存在的时候:
        文件的名称:1.txt
        文件的大小:22
        最后修改时间:1578965853497  毫秒值,距离1970年1月1日凌晨的毫秒值
        file是代表一个文件吗?true
        file是代表一个目录吗?false
        文件可读吗:true
        文件可写吗:true
        是隐藏文件吗?false
        文件存在码?true
         */
    }


    @Test
    public void test01(){
        //表示D盘下1.txt文件
        File file = new File("d:/1.txt");//这个文件不存在,不影响我new对象

        //表示D盘下atguigu文件夹
        File dir = new File("d:/atguigu");
    }
}

3、文件和目录的创建、删除、重命名等操作

(1)createNewFile():只能创建文件,不能创建目录
(2)mkdir():创建目录
(3)mkdirs():创建目录,但是如果这个目录的父目录不存在,也一并创建
(4)delete():删除文件或目录
如果目录非空,使用delete是无法直接删除的
(5)renameTo(File dest)

(6)static File createTempFile(String prefix, String suffix) :创建临时目录
在默认临时目录中生成:C:\Users\Irene\AppData\Local\Temp

static File createTempFile(String prefix, String suffix, File directory)
在指定目录中生成临时文件

(7)void deleteOnExit() :在退出程序时删除

一般会配合void deleteOnExit() 使用

public class TestFileCreate {
    @Test
    public void test08() throws IOException, InterruptedException {
        File file = File.createTempFile("atguigu", null);
        Thread.sleep(3000);
        file.deleteOnExit();
    }


    @Test
    public void test07() throws IOException {
        File file =new File("d:/1.txt");
        File dest = new File("d:/hello.txt");

        System.out.println("重名名之前:"+ file.length());//46

        file.renameTo(dest);

        System.out.println("重名名之后:"+ file.length());//0  file对象已经被重名了,不存在了
    }

    @Test
    public void test06() throws IOException {
        File file =new File("d:/QMDownload");
        file.delete();
    }


    @Test
    public void test05() throws IOException {
        File file =new File("d:/1.txt");
        file.delete();
    }

    @Test
    public void test04() throws IOException {
        File file =new File("d:/chailinyan");
        file.delete();
    }

    @Test
    public void test03() throws IOException {
        //file对象代表的是code这个目录,不能代表三个目录
        //其中1213,java是为了描述code目录的路径,它是父目录
        File file =new File("d:/1213/java/code");
//        file.mkdir();
        file.mkdirs();
    }


    @Test
    public void test02() throws IOException {
        File file =new File("d:/chailinyan");
        file.mkdir();
    }

    @Test
    public void test01() throws IOException {
        File file =new File("d:/1.txt");
        file.createNewFile();//当路径有问题,或者说没有权限等原因会导致文件创建失败,就报异常
    }
}

二、java.io包的各种IO流

1、什么是IO流?

I:Input:数据的读取、输入
O:Output:数据的写、输出
IO:数据的输入和输出、数据的读和写
数据的读取:可以从指定的文件读取,可以从网络接收,可以从一块内存读取到另一块内存…
数据的写:可以写入指定的文件,可以发送到网络的某个端点(服务器端或客户端),也可以从一块内存写到另一块内存…

后面要学习的web,数据库都要用到IO,只不过是它们底层用到了,我们上层看不见这个代码,除非看底层源码。

IO流:数据的输入、输出的“通道”,即相关的类型

2、传统的IO流的分类

(1)按照方向分:
输入流和输出流。
输入流:我们的程序只能从输入流中读取数据。
输出流:我们的程序只能把数据写到输出流中,不能从输出流中读数据。

(2)按照处理的数据的方式不同
字节流和字符流。
字节流:适用于处理任意类型的数据。以字节为单位。可以一个字节一个字节处理,也可以多个字节一起处理。
字符流:只能用于处理纯文本数据。以字符为单位。可以一个字符一个字符处理,也可以多个字符一起处理。
纯文本的数据:就是字符串(String)、字符char
纯文本文件:.txt, .html, .css, .js, .xml, .java 等
非纯文本文件:.class, .jpg等图片, .avi等视频, .doc,.ppt,.xls等文档,.exe等

(3)按照IO流的作用不同
节点流和处理流。
节点流:从数据节点读取数据,或把数据写到数据节点中。
数据节点:例如:文件,数组等可以装数据的容器。
处理流:用于装饰节点流,在节点流的基础上增加辅助的功能,例如:缓冲功能、序列化和反序列化、编码与解码功能等
处理流是必须结合节点流才能使用的。
反过来,节点流可以单独工作。

3、IO流的四大抽象基类:

InputStream:字节输入流,只能从这个系列的类型的IO中读取字节数据
OutputStream:字节输出流,针对它,只能写出,输出字节数据。
Reader:字符输入流,只能从这个系列的类型的IO中读取字符数据
Writer:字符输出流,针对它,只能写出,输出字符数据。

4、派生其他的IO流

(1)文件IO流
FileInputStream:文件字节输入流,以字节的方式从文件中读取数据
FileOutputStream:文件字节输出流,以字节的方式把数据写到文件中,输出到文件中
FileReader:文件字符输入流,以字符的方式从文件中读取数据
FileWriter:文件字符输出流,以字符的方式把数据写到文件中,输出到文件中

(2)缓冲IO流
BufferedInputStream:字节缓冲输入流,专门给InputStream系列的输入流增加缓冲功能
BufferedOutputStream:字节缓冲输出流,专门给OutputStream系列的输出流增加缓冲功能
BufferedReader:字符缓冲输入流,专门给Reader系列的输入流增加缓冲功能
BufferedWriter:字符缓冲输出流,专门给Writer系列的输出流增加缓冲功能

(3)编码与解码IO流
InputStreamReader:解码IO流,把原先InputStream系列字节输入流的字节数据转换为Reader系列字符输入流的字符数据,读入。
OutputStreamWriter:编码IO流,把原先Writer系列字符输出流的字符数据转为为OutputStream系列字节输出流的字节数据,写出。

(4)数据IO流
DataInputStream:数据字节输入流,以字节的方式读取Java的各种基本数据类型的数据和字符串。
DataOutputStream:数据字节输出流,以字节的方式写出Java的各种基本数据类型的数据和字符串。

(5)对象IO流
ObjectInputStream:对象的字节输入流,以字节的方式读取一个Java对象。
ObjectOutputStream:对象的字节输出流,以字节的方式输出一个Java对象。

(6)打印流
PrintStream:字节输出流
PrintWriter:字符输出流

(8)文本扫描仪:
Scanner:从指定的输入流中读取数据
例如:System.in中读取数据

三、文件IO流

1、FileInputStream:

是InputStream的子类,用于从文件读取数据,按字节的方式读取
字节输入流既可以读取纯文本文件,也可以读取其他类型的文件。

步骤:
(1)创建IO流对象
创建FileInputStream的对象,并且指定从哪个文件读取数据
(2)读取
从输入流中读取
A:int read():一次读取一个字节,如果有数据,返回读取到的字节数据的值,如果流中已经没有数据了,返回-1
B:int read(byte[] data):一次读取多个字节。返回的是本次读取的字节的数量。如果流中已经没有数据了,返回-1
一次最多读取data.length个,如果流中的数据没有data.length个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[0]开始存。
C:int read(byte[] data, int off, int count):一次读取多个字节。返回的是本次读取的字节的数量。如果流中已经没有数据了,返回-1
一次最多读取count个,如果流中的数据没有count个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[off]开始存。

(3)关闭IO流
close()

public class TestFileInputStream {
    @Test
    public void test04() throws IOException {
        FileInputStream fis = new FileInputStream("D:\\QMDownload\\img\\下载.jpg");
        int result;
        byte[] data = new byte[1024];
        while((result = fis.read(data))!=-1){
            System.out.println(result);
//            System.out.println(new String(data,0,result));//在控制台无法用字符显示图片的内容,除非把字节数据,传给图片查看工具才可以显示图片
        }

        fis.close();
    }

    @Test
    public void test03() throws IOException {
        //读取d:/1.txt文件
        //路径:d:/1.txt  或  d:\\1.txt
        FileInputStream fis = new FileInputStream("d:/1.txt");
        //读取时文件不存在会报错

        int result;
        byte[] data = new byte[4];
        while((result = fis.read(data))!=-1){
//            System.out.println(result);//读取的字节数
//            System.out.println(Arrays.toString(data));//显示字节的值
            //String(byte[] bytes)
            //String(byte[] bytes, int offset, int length)
            System.out.println(new String(data,0,result));//字节数组的数据,如何显示为字符串
        }


        fis.close();
    }


    @Test
    public void test02() throws IOException {
        //读取d:/1.txt文件
        //路径:d:/1.txt  或  d:\\1.txt
        FileInputStream fis = new FileInputStream("d:/1.txt");
        int result;
        while((result = fis.read())!=-1){
            System.out.println(result);
        }

        fis.close();
    }

    //FileNotFoundException是IOException的子类,都是编译时异常
    @Test
    public void test01() throws IOException {
        //读取d:/1.txt文件
        //路径:d:/1.txt  或  d:\\1.txt
        FileInputStream fis = new FileInputStream("d:/1.txt");
        System.out.println(fis.read());//104  104是h的编码值
        System.out.println(fis.read());//101  101是e的编码值
        System.out.println(fis.read());//108  108是l的编码值
        System.out.println(fis.read());//108  108是l的编码值
        System.out.println(fis.read());//111  111是o的编码值
        System.out.println(fis.read());//-1   -1表示流中没有数据了

        fis.close();
    }
}

2、FileOutputStream:

是OutputStream的子类,按照字节输出内容到文件中
步骤:
(1)创建IO流对象
创建FileOutputStream对象,告知写出到哪个文件中

(2)输出内容
A:write(int b):写一个字节
B:write(byte[] data):写整个字节数组
C:write(byte[] data,int offset, int count):写出data[offset]开始的count个字节

(3)关闭IO流
close()

public class TestFileOutputStream {
    @Test
    public void test02() throws IOException {
        //写  今天是放假倒数第三天  到 项目的day23_teacher_code模块的根目录下的2.txt文件中
        FileOutputStream fos = new FileOutputStream("upload/2.txt");//相对路径表示方式
        //文件不存在,会自动创建
        //目录不存在,会报错

        String str = "今天是放假倒数第三天";
        //如何把字符串转为字节数组?
        //byte[] getBytes()
        byte[] bytes = str.getBytes();

        fos.write(bytes);

        fos.close();
    }

    @Test
    public void test01() throws IOException {
        //写  今天是放假倒数第三天  到 项目的day23_teacher_code模块的根目录下的2.txt文件中
        FileOutputStream fos = new FileOutputStream("2.txt");//相对路径表示方式
        //文件不存在,会自动创建
        //目录不存在,会报错

        String str = "今天是放假倒数第三天";
        //如何把字符串转为字节数组?
        //byte[] getBytes()
        byte[] bytes = str.getBytes();

        fos.write(bytes);

        fos.close();
    }
}

3、FileReader:

是Reader的子类,只能读取纯文本文件

步骤:
(1)创建FileReader对象
(2)读取
从输入流中读取
A:int read():一次读取一个字符,如果有数据,返回读取到的字符数据的值,如果流中已经没有数据了,返回-1
B:int read(char[] data):一次读取多个字符。返回的是本次读取的字符的数量。如果流中已经没有数据了,返回-1
一次最多读取data.length个,如果流中的数据没有data.length个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[0]开始存。
C:int read(char[] data, int off, int count):一次读取多个字符。返回的是本次读取的字符的数量。如果流中已经没有数据了,返回-1
一次最多读取count个,如果流中的数据没有count个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[off]开始存。

乱码的原因:
(1)缺字节
(2)编码方式不对

public class TestFileReader {
    @Test
    public void test02() throws IOException {
        FileReader fr = new FileReader("d:/1.txt");
        char[] data = new char[3];
        int len;
        while((len = fr.read(data)) != -1){
            System.out.println(new String(data,0,len));//len表示读取了几个字符
        }
        fr.close();
    }

    @Test
    public void test01() throws IOException {
        FileReader fr = new FileReader("d:/1.txt");
        System.out.println(fr.read());//读取一个字符,读取的是字符的编码值,如果是汉字也是整个汉字的Unicode编码值
    }
}

4、FileWriter:

是Writer的子类,把数据以字符、字符串的方式写到文件中
步骤:
(1)创建IO流对象
创建FileWriter对象,告知写出到哪个文件中

(2)输出内容
A:write(int b):写一个字符
B:write(char[] data):写整个字符数组
C:write(char[] data,int offset, int count):写出data[offset]开始的count个字符

(3)关闭IO流
close()

public class TestFileWriter {
    @Test
    public void test01() throws IOException {
        //true:表示追加方式,即在原来文件末尾接着写
        FileWriter fw = new FileWriter("1.txt",true);//相对路径
        //输出一句话,电脑该换了
        String str = "过年等着大家发红包买电脑";
        fw.write(str);
        fw.close();
    }

    @Test
    public void test02() throws IOException {
        FileWriter fw = new FileWriter("1.txt");//相对路径
        //输出一句话,电脑该换了
        String str = "过年等着大家发红包买电脑";
        fw.write(str);
        fw.close();
    }
}

四、缓冲IO流

1、BufferedInputStream:

字节缓冲输入流,专门给InputStream系列的输入流增加缓冲功能

2、BufferedOutputStream:

字节缓冲输出流,专门给OutputStream系列的输出流增加缓冲功能

3、BufferedReader:

字符缓冲输入流,专门给Reader系列的输入流增加缓冲功能
比父类增加了一个方法:String readLine()

4、BufferedWriter:

字符缓冲输出流,专门给Writer系列的输出流增加缓冲功能
比父类增加了一个方法:void newLine()

作用:提高效率
private static int DEFAULT_BUFFER_SIZE = 8192;默认缓冲大小
byte[]
char[]

public class TestBuffer {
    @Test
    public void test01() throws IOException {
        FileInputStream fis = new FileInputStream("1.txt");
        //给fis这个字节输入流,增加缓冲功能,把数据先放到bis的缓冲区中
        BufferedInputStream bis = new BufferedInputStream(fis);

        //数据:1.txt==>fis==>bis
        //接下来的程序,应该从bis输入流中读取数据
        byte[] data = new byte[1024];
        int len;
        while((len = bis.read(data))!=-1){
            System.out.println(new String(data,0,len));
        }

        // BufferedInputStream bis = new BufferedInputStream(fis);bis是外面的,fis是里面的
        //关闭的顺序,先关外面的,再关里面的
        bis.close();
        fis.close();
    }

    @Test
    public void test02() throws IOException{
        FileOutputStream fos = new FileOutputStream("1.txt",true);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //数据:程序==>bos==>fos==>1.txt
        bos.write("马上放假了".getBytes());

        bos.close();
        fos.close();
    }

    @Test
    public void test03() throws IOException{
        FileReader fr = new FileReader("1.txt");
        BufferedReader br = new BufferedReader(fr);

        //数据:1.txt==>fr==>br==>程序data
        char[] data = new char[1024];
        int len;
        while((len = br.read(data))!=-1){
            System.out.println(new String(data,0,len));
        }

        br.close();
        fr.close();
    }

    @Test
    public void test033() throws IOException{
        FileReader fr = new FileReader("1.txt");
        BufferedReader br = new BufferedReader(fr);

        //数据:1.txt==>fr==>br==>程序
        String str;
        //null表示到达流末尾了,不是说空行
        while((str = br.readLine()) != null){
            System.out.println(str);
        }
        br.close();
        fr.close();
    }


    @Test
    public void test04() throws IOException {
        FileWriter fw = new FileWriter("1.txt",true);
        BufferedWriter bw = new BufferedWriter(fw);

        //数据:程序==>bw==>fw==>1.txt
//        bw.write("\r\n");//输出换行符
        bw.newLine();//输出换行符
        bw.write("玩游戏必须上报");
        bw.flush();//刷新

        bw.close();//如果没有刷新,没有关闭缓冲流,很可能数据在缓冲区中没有正式写出
        fw.close();
    }
}

public class FileUtils {
    /**
     * 从srcFilePath文件中复制生成destFilePath
     * @param srcFilePath String:源文件的路径名
     * @param destFilePath String:目标文件的路径名
     */
    public static void copy(String srcFilePath, String destFilePath)throws IOException {
        long start = System.currentTimeMillis();
        //选择什么IO流:字节流还是字符流,这里选择字节流,因为没有说一定是纯文本文件
        //复制文件:既需要读取又需要写
        FileInputStream fis = new FileInputStream(srcFilePath);
        FileOutputStream fos = new FileOutputStream(destFilePath);

        //一边读从fis输入流中读取数据,一边写到fos输出流中
        //每次读取多个字节
        byte[] data = new byte[1024];
        int len;
        //从fis读取的数据临时存储在data中
        while((len = fis.read(data)) != -1){
            //从data数组中取出来,写到fos中
            fos.write(data,0,len);
        }

        //关闭
        fis.close();
        fos.close();

        long end = System.currentTimeMillis();
        System.out.println("没有使用缓冲流的时间:" + (end-start));
    }

    public static void copyBuffer(String srcFilePath, String destFilePath)throws IOException {
        long start = System.currentTimeMillis();

        //选择什么IO流:字节流还是字符流,这里选择字节流,因为没有说一定是纯文本文件
        //复制文件:既需要读取又需要写
        FileInputStream fis = new FileInputStream(srcFilePath);
        BufferedInputStream bis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream(destFilePath);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //srcFilePath文件==>fis==>bis ==>程序的data==> bos==>fos==>destFilePath
        //每次读取多个字节
        byte[] data = new byte[1024];
        int len;
        //从fis读取的数据临时存储在data中
        while((len = bis.read(data)) != -1){
            //从data数组中取出来,写到fos中
            bos.write(data,0,len);
        }

        //关闭
        bis.close();
        fis.close();

        bos.close();
        fos.close();

        long end = System.currentTimeMillis();
        System.out.println("使用缓冲流的时间:" + (end-start));
    }
}

public class TestFileUtils {
    public static void main(String[] args) throws IOException {
        FileUtils.copy("D:\\software\\IDEA\\ideaIU-Ultimate-2019.2.3.exe","d:\\1.exe");
        //没有使用缓冲流的时间:23048毫秒

        FileUtils.copyBuffer("D:\\software\\IDEA\\ideaIU-Ultimate-2019.2.3.exe","d:\\2.exe");
        //使用缓冲流的时间:4947毫秒


    }
}

五、编码与解码IO流

1、解码IO流:InputStreamReader

从字节流中读取数据,按照指定的编码方式,解码为字符流

2、编码IO流

从字符流中写出数据,按照指定的编码方式,编码为字节流

编码:
把字符/字符串==>字节序列的过程
解码:
把字节==>字符/字符串的过程

人只能看懂字符/字符串,机器只识别字节。

public class TestTransfer {

    @Test
    public void test04() throws IOException {
        FileOutputStream fos = new FileOutputStream("d:/1.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");

        //数据:程序==》osw ==>按照指定的编码,把数据从字符转为字节==> fos ==> d:/1.txt
        osw.write("大家都着急了");

        osw.close();
        fos.close();
    }
    @Test
    public void test03() throws IOException {
        FileWriter fw = new FileWriter("d:/1.txt",true);
        fw.write("大家都着急了");
        fw.close();
    }
    @Test
    public void test02() throws IOException {
        //如果需要解码,按照GBK进行解码
        //在内存中解码,不是在文件中间解码
        //先把文件中的数据 原样(按照字节读取) 读取到内存,然后再内存中进行解码
        FileInputStream fis = new FileInputStream("d:/1.txt");

        //数据已经从d:/1.txt ==> fis(字节)在内存中
        //从fis读取字节数据的过程中进行解码为字符
        InputStreamReader isr = new InputStreamReader(fis,"GBK");//isr从fis中读取数据,并按照指定的编码方式进行解码为字符

        //接下来的程序就要重isr中读取数据
        char[] data = new char[10];
        int len;
        while((len = isr.read(data))!=-1){
            System.out.println(new String(data,0,len));
        }

        isr.close();
        fis.close();
    }


    @Test
    public void test01() throws IOException {
        //d:/1.txt是GBK
        //程序是UTF-8
        //FileReader只会按照程序中的编码方式进行解码,无法手动指定编码
        FileReader fr = new FileReader("d:/1.txt");

        char[] data = new char[10];
        int len;
        while((len = fr.read(data))!=-1){
            System.out.println(new String(data,0,len));
        }

        fr.close();
    }
}

六、数据IO流

DataInputStream:

数据字节输入流,以字节的方式读取Java的各种基本数据类型的数据和字符串。

DataOutputStream:

数据字节输出流,以字节的方式写出Java的各种基本数据类型的数据和字符串。

DataInputStream给InputStream系列的IO流增加辅助功能,可以处理Java的各种基本数据类型的数据
DataOutputStream给OutputStream系列的IO流增加辅助功能,可以处理Java的各种基本数据类型的数据

public class TestDataIO {

    @Test
    public void test04() throws IOException {
        FileInputStream fis = new FileInputStream("d:/ban.txt");
        DataInputStream dis = new DataInputStream(fis);
        //数据:d:/ban.txt==》fis==>dis==>程序
        String name = dis.readUTF();
        int age = dis.readInt();
        char gender = dis.readChar();
        double weight = dis.readDouble();
        boolean marry = dis.readBoolean();

        System.out.println(name);
        System.out.println(age);
        System.out.println(gender);
        System.out.println(weight);
        System.out.println(marry);

        dis.close();
        fis.close();
    }
    @Test
    public void test03() throws IOException {
        //写到文件中,并且要按照对应的数据类型写出
        String name = "小张";
        int age = 28;
        char gender = '男';
        double weight = 65.5;
        boolean marry = true;

        FileOutputStream fos = new FileOutputStream("d:/ban.txt");
        DataOutputStream dos = new DataOutputStream(fos);
        //数据:程序==>dos==>fos==>d:/ban.txt
        //这里写出去的不是纯文本数据,使用.txt的后缀,用文本编辑打开,也是无法还原数据,即看不懂
        //只有再次使用Java的程序读取到程序中才能正确识别。因为它里面不仅有数据,还有Java的数据类型的信息
        //所以使用普通的文本编辑是无法打开。

        dos.writeUTF(name);
        dos.writeInt(age);
        dos.writeChar(gender);
        dos.writeDouble(weight);
        dos.writeBoolean(marry);

        dos.close();
        fos.close();
    }


    @Test
    public void test02() throws IOException {
        FileReader fr = new FileReader("d:/ban.txt");
//        fr.read()//无法区分每一项数据有几个字符
    }

    @Test
    public void test01() throws IOException {
        //写到文件中,并且要按照对应的数据类型写出
        String name = "小张";
        int age = 28;
        char gender = '男';
        double weight = 65.5;
        boolean marry = true;

       /* FileOutputStream fos = new FileOutputStream("d:/ban.txt");
        fos.write(name.getBytes());
        fos.write(age);
        fos.write(gender);
        fos.write(weight);
        fos.write(marry);*/

        FileWriter fw = new FileWriter("d:/ban.txt");
        fw.write(name);
        fw.write(age);//把age的值当成字符编码值写出
        fw.write(gender);
        fw.write(weight+"");
        fw.write(marry+"");

        fw.close();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值