JAVA-异常&IO流

本文深入解析Java异常处理机制,包括异常的概念、继承体系、处理方式及自定义异常,并详细阐述IO流的分类、使用及优化技巧,涵盖字节流、字符流、序列流等多种流类型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常的概述:
异常就是Java程序在运行过程中出现的错误

异常的继承体系
    Throwable
        Error    
        Exception
            RuntimeException


JVM默认是如何处理异常的
    * main函数收到这个问题时,有两种处理方式:
    * a:自己将该问题处理,然后继续运行
    * b:自己没有针对的处理方式,只有交给调用main的jvm来处理
    * jvm有一个默认的异常处理机制,就将该异常进行处理.
    * 并将该异常的名称,异常的信息.异常出现的位置打印在了控制台上,同时将程序停止运行

 

异常处理的两种方式
    * a:try…catch…finally
        * try catch
        * try catch finally
        * try finally 
    * b:throws
try...catch处理异常的基本格式
    * try…catch…finally

try:用来检测异常的
catch:用来捕获异常的
finally:释放资源

例:try {
            System.out.println(a / b);
            System.out.println(arr[10]);
        } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
            System.out.println("出错了");
        } 

安卓,客户端开发,如何处理异常?try{}catch(Exception e){}
ee,服务端开发,一般都是底层开发,从底层向上抛
try后面如果跟多个catch,那么小的异常放前面,大的异常放后面,根据多态的原理,如果大的放前面,就会将所有的子类对象接收后面的catch就没有意义了

 

Throwable的几个常见方法
    * a:getMessage()
        * 获取异常信息,返回字符串。
    * b:toString()
        * 获取异常类名和异常信息,返回字符串。
    * c:printStackTrace()
        * 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。

throws的方式处理异常
    * 定义功能方法时,需要把出现的问题暴露出来让调用者去处理。
    * 那么就通过throws在方法上标识。

throw的概述
    * 在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

try {
            System.out.println(1/0);
        } catch (Exception e) {            //Exception e = new ArithmeticException("/ by zero");
            //System.out.println(e.getMessage());        //获取异常信息
            //System.out.println(e);         //调用toString方法,打印异常类名和异常信息
            e.printStackTrace();        //jvm默认就用这种方式处理异常
        }

throws和throw的区别
    * a:throws
        * 用在方法声明后面,跟的是异常类名
        * 可以跟多个异常类名,用逗号隔开
        * 表示抛出异常,由该方法的调用者来处理
    * b:throw
        * 用在方法体内,跟的是异常对象名
        * 只能抛出一个异常对象名
        * 表示抛出异常,由方法体内的语句处理

finally的特点
    * 被finally控制的语句体一定会执行
    * 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))

finally的作用
    * 用于释放资源,在IO流操作和数据库操作中会见到

final,finally和finalize的区别:

* final可以修饰类,不能被继承
修饰方法,不能被重写
修饰变量,只能赋值一次
* finally是try语句中的一个语句体,不能单独使用,用来释放资源
 * finalize是一个方法,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

 

如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后:

 

自定义异常概述
    * 继承自Exception
    * 继承自RuntimeException

异常注意事项
    * a:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
    * b:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
    * c:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
如何使用异常处理
    * 原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws
    * 区别:
        * 后续程序需要继续运行就try
        * 后续程序不需要继续运行就throws     
    * 如果JDK没有提供对应的异常,需要自定义异常。

alt+shift+z:try catch快捷键

ctrl+e抛出异常

File类的概述
    * File更应该叫做一个路径
        * 文件路径或者文件夹路径  
        * 路径分为绝对路径和相对路径
        * 绝对路径是一个固定的路径,从盘符开始
        * 相对路径相对于某个位置,在eclipse下是指当前项目下,在dos下
    * 查看API指的是当前路径
    * 文件和目录路径名的抽象表示形式

构造方法
    * File(String pathname):根据一个路径得到File对象
    * File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
    * File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象

File类的创建功能

* public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
* public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
* public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来

File dir3 = new File("ccc\\ddd");         //需要转义分隔符“\”所以需要"\\"或者"/"都行
        System.out.println(dir3.mkdirs());                 //创建多级目录

重命名和删除功能
    * public boolean renameTo(File dest):把文件重命名为指定的文件路径
    * public boolean delete():删除文件或者文件夹
重命名注意事项
    * 如果路径名相同,就是改名。
    * 如果路径名不同,就是改名并剪切。
删除注意事项:
    * Java中的删除不走回收站。
    * 要删除一个文件夹,请注意该文件夹内不能包含文件或者文件夹

判断功能
    * public boolean isDirectory():判断是否是目录
    * public boolean isFile():判断是否是文件
    * public boolean exists():判断是否存在
    * public boolean canRead():判断是否可读
    * public boolean canWrite():判断是否可写
    * public boolean isHidden():判断是否隐藏

System.out.println(file.canRead());             //windows系统认为所有的文件都是可读的
        file.setWritable(true);
        System.out.println(file.canWrite());             //windows系统可以设置为不可写

 

获取功能
    * public String getAbsolutePath():获取绝对路径
    * public String getPath():获取路径
    * public String getName():获取名称
    * public long length():获取长度。字节数
    * public long lastModified():获取最后一次的修改时间,毫秒值

Date d = new Date(file1.lastModified());                //文件的最后修改时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
System.out.println(sdf.format(d));
    * public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
    * public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组 

文件名称过滤器的概述
    * public String[] list(FilenameFilter filter)
    * public File[] listFiles(FileFilter filter)
文件名称过滤器的使用
    * 需求:判断E盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称

    * 带文件名称过滤器的list()方法的源码

public static void main(String[] args) {
        File dir = new File("D:\\");        
//        String[] arr = dir.list();                    //获取e盘下所有的文件或文件夹
//        for (String string : arr) {
//            if(string.endsWith(".jpg")) {
//                System.out.println(string);
//            }
//        }
        
        /*File[] subFiles = dir.listFiles();            //获取e盘下所有的文件或文件夹对象
        
        for (File subFile : subFiles) {
            if(subFile.isFile() && subFile.getName().endsWith(".jpg")) {
                System.out.println(subFile);
            }
        }*/
        
        String[] arr = dir.list(new FilenameFilter() {
            
            @Override    //表示重写方法的注释
            public boolean accept(File dir, String name) {
                //System.out.println(dir);
                //System.out.println(name);
                File file = new File(dir, name);
                return file.isFile() && file.getName().endsWith(".jpg");
            }
        });
        
        for (String string : arr) {
            System.out.println(string);
        }
    }
 

IO流概述及其分类

概念
    * IO流用来处理设备之间的数据传输
    * Java对数据的操作是通过流的方式
    * Java用于操作流的类都在IO包中
    * 流按流向分为两种:输入流,输出流。
    * 流按操作类型分为两种:
        * 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
        * 字符流 : 字符流只能操作纯字符数据,比较方便。

IO流常用父类
    * 字节流的抽象父类:
        * InputStream 
        * OutputStream
    * 字符流的抽象父类:
        * Reader 
        * Writer    

程序书写
    * 使用前,导入IO包中的类
    * 使用时,进行IO异常处理
    * 使用后,释放资源

FileInputStream:

read()一次读取一个字节
        FileInputStream fis = new FileInputStream("aaa.txt");    //创建一个文件输入流对象,并关联aaa.txt
        int b;                                                    //定义变量,记录每次读到的字节
        while((b = fis.read()) != -1) {                            //将每次读到的字节赋值给b并判断是否是-1
            System.out.println(b);                                //打印每一个字节
        }  
        fis.close();                                            //关闭流释放资源

read()方法返回值为什么是int?

因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111,那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

 

FileOutputStream
* write()一次写出一个字节
        FileOutputStream fos = new FileOutputStream("bbb.txt");    //如果没有bbb.txt,会创建出一个
        //fos.write(97);                        //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的是一个byte
        fos.write(98);
        fos.write(99);
        fos.close();


FileOutputStream追加
* A:案例演示
 * FileOutputStream的构造方法写出数据如何实现数据的追加写入
        FileOutputStream fos = new FileOutputStream("bbb.txt",true);    //如果没有bbb.txt,会创建出一个
        //fos.write(97);                        //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个byte
        fos.write(98);
        fos.write(99);
        fos.close();

###20.06_IO流(拷贝图片)
* FileInputStream读取
* FileOutputStream写出

        FileInputStream fis = new FileInputStream("致青春.mp3");    //创建输入流对象,关联致青春.mp3
        FileOutputStream fos = new FileOutputStream("copy.mp3");//创建输出流对象,关联copy.mp3     
        int b;
        while((b = fis.read()) != -1) {
            fos.write(b);
        } 
        fis.close();
        fos.close();
        

拷贝音频文件画原理图
* A:案例演示
    * 字节流一次读写一个字节复制音频
* 弊端:效率太低

 

字节数组拷贝之available()方法
* A:案例演示
    * int read(byte[] b):一次读取一个字节数组
    * write(byte[] b):一次写出一个字节数组
    * available()获取读的文件所有的字节个数
* 弊端:有可能会内存溢出 
    
        FileInputStream fis = new FileInputStream("致青春.mp3");
        FileOutputStream fos = new FileOutputStream("copy.mp3");
        byte[] arr = new byte[fis.available()];                    //根据文件大小做一个字节数组
        fis.read(arr);                                            //将文件上的所有字节读取到数组中
        fos.write(arr);                                            //将数组中的所有字节一次写到了文件上
        fis.close();
        fos.close();
        
定义小数组
* write(byte[] b)
* write(byte[] b, int off, int len)写出有效的字节个数

        
定义小数组的标准格式
* A:案例演示
* 字节流一次读写一个字节数组复制图片和视频
        FileInputStream fis = new FileInputStream("致青春.mp3");
        FileOutputStream fos = new FileOutputStream("copy.mp3");
        int len;
        byte[] arr = new byte[1024 * 8];                    //自定义字节数组
        while((len = fis.read(arr)) != -1) {
            //fos.write(arr);
            fos.write(arr, 0, len);                            //写出字节数组写出有效个字节个数
        }
        fis.close();
        fos.close();


BufferedInputStream和BufferOutputStream拷贝
* A:缓冲思想
    * 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
    * 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
    * 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
* B.BufferedInputStream
    * BufferedInputStream内置了一个缓冲区(数组)
    * 从BufferedInputStream中读取一个字节时
    * BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
    * 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
    * 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
* C.BufferedOutputStream
    * BufferedOutputStream也内置了一个缓冲区(数组)
    * 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
    * 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
* D.拷贝的代码 

        FileInputStream fis = new FileInputStream("致青春.mp3");            //创建文件输入流对象,关联致青春.mp3
        BufferedInputStream bis = new BufferedInputStream(fis);            //创建缓冲区对fis装饰
        FileOutputStream fos = new FileOutputStream("copy.mp3");        //创建输出流对象,关联copy.mp3
        BufferedOutputStream bos = new BufferedOutputStream(fos);        //创建缓冲区对fos装饰
        int b;
        while((b = bis.read()) != -1) {        
            bos.write(b);
        }
        bis.close();                        //只关装饰后的对象即可
        bos.close();
     
* E.小数组的读写和带Buffered的读取哪个更快?
    * 定义小数组如果是8192个字节大小和Buffered比较的话
    * 定义小数组会略胜一筹,因为读和写操作的是同一个数组
    * 而Buffered操作的是两个数组

 

flush和close方法的区别
* flush()方法
    * 用来刷新缓冲区的,刷新后可以再次写出 
* close()方法
    * 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出 


字节流读写中文
* 字节流读取中文的问题
    * 字节流在读中文的时候有可能会读到半个中文,造成乱码 
* 字节流写出中文的问题
    * 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组 
    * 写出回车换行 write("\r\n".getBytes());

流的标准处理异常代码 1.6版本及其以前
* try finally嵌套

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("aaa.txt");
            fos = new FileOutputStream("bbb.txt");
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        } finally {
            try {
                if(fis != null)
                    fis.close();
            }finally {
                if(fos != null)
                    fos.close();
            }
        }

 

流的标准处理异常代码1.7版本
* try close

        try(
            FileInputStream fis = new FileInputStream("aaa.txt");
            FileOutputStream fos = new FileOutputStream("bbb.txt");
            MyClose mc = new MyClose();
        ){
            int b;
            while((b = fis.read()) != -1) {
                fos.write(b);
            }
        }
* 原理
    * 在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉 

 

图片加密
* 给图片加密

        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.jpg")); 
        int b;
        while((b = bis.read()) != -1) {
            bos.write(b ^ 123);
        }
        bis.close();
        bos.close();

 

拷贝文件
* 在控制台录入文件的路径,将文件拷贝到当前项目下

        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个文件路径");
        String line = sc.nextLine();                //将键盘录入的文件路径存储在line中
        File file = new File(line);                    //封装成File对象
        FileInputStream fis = new FileInputStream(file);
        FileOutputStream fos = new FileOutputStream(file.getName());
        int len;
        byte[] arr = new byte[8192];                //定义缓冲区
        while((len = fis.read(arr)) != -1) {
            fos.write(arr,0,len);
        }
        fis.close();
        fos.close();

 

录入数据拷贝到文件
* 将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出

        Scanner sc = new Scanner(System.in);
        FileOutputStream fos = new FileOutputStream("text.txt");
        System.out.println("请输入:");
        while(true) {
            String line = sc.nextLine();
            if("quit".equals(line))
                break;
            fos.write(line.getBytes());
            fos.write("\r\n".getBytes());
        }
        fos.close();

 

字符流FileReader
* 1.字符流是什么
    * 字符流是可以直接读写字符的IO流
    * 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出.    
* 2.FileReader
    * FileReader类的read()方法可以按照字符大小读取

        FileReader fr = new FileReader("aaa.txt");                //创建输入流对象,关联aaa.txt
        int ch;
        while((ch = fr.read()) != -1) {                            //将读到的字符赋值给ch
            System.out.println((char)ch);                        //将读到的字符强转后打印
        }
        
        fr.close();                                                //关流 

字符流FileWriter
* FileWriter类的write()方法可以自动把字符转为字节写出

        FileWriter fw = new FileWriter("aaa.txt");
        fw.write("aaa");
        fw.close();

字符流的拷贝
    FileReader fr = new FileReader("a.txt");
    FileWriter fw = new FileWriter("b.txt");
    
    int ch;
    while((ch = fr.read()) != -1) {
        fw.write(ch);
    }
    
    fr.close();
    fw.close();


什么情况下使用字符流
* 字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.
* 程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流
* 读取的时候是按照字符的大小读取的,不会出现半个中文
* 写出的时候可以直接将字符串写出,不用转换为字节数组

字符流是否可以拷贝非纯文本的文件
* 不可以拷贝非纯文本的文件
* 因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
* 如果是?,直接写出,这样写出之后的文件就乱了,看不了了  

自定义字符数组的拷贝
        FileReader fr = new FileReader("aaa.txt");            //创建字符输入流,关联aaa.txt
        FileWriter fw = new FileWriter("bbb.txt");            //创建字符输出流,关联bbb.txt
        
        int len;
        char[] arr = new char[1024*8];                        //创建字符数组
        while((len = fr.read(arr)) != -1) {                    //将数据读到字符数组中
            fw.write(arr, 0, len);                            //从字符数组将数据写到文件上
        }
        
        fr.close();                                            //关流释放资源
        fw.close();    

带缓冲的字符流
* BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
* BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率

        BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));    //创建字符输入流对象,关联aaa.txt
        BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));    //创建字符输出流对象,关联bbb.txt
        
        int ch;                
        while((ch = br.read()) != -1) {        //read一次,会先将缓冲区读满,从缓冲去中一个一个的返给临时变量ch
            bw.write(ch);                    //write一次,是将数据装到字符数组,装满后再一起写出去
        }
        
        br.close();                            //关流
        bw.close();  


readLine()和newLine()方法
* BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
* BufferedWriter的newLine()可以输出一个跨平台的换行符号"\r\n"

        BufferedReader br = new BufferedReader(new FileReader("aaa.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("bbb.txt"));
        String line;
        while((line = br.readLine()) != null) {
            bw.write(line);
            //bw.write("\r\n");                    //只支持windows系统
            bw.newLine();                        //跨平台的
        }
        
        br.close();
        bw.close(); 

将文本反转
* 将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换

LineNumberReader
* LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
    * 调用getLineNumber()方法可以获取当前行号
    * 调用setLineNumber()方法可以设置当前行号

        LineNumberReader lnr = new LineNumberReader(new FileReader("aaa.txt"));
        String line;
        lnr.setLineNumber(100);                                    //设置行号
        while((line = lnr.readLine()) != null) {
            System.out.println(lnr.getLineNumber() + ":" + line);//获取行号
        }
        lnr.close(); 

 

装饰设计模式
        interface Coder {
            public void code();
        }
        
        class Student implements Coder {
        
            @Override
            public void code() {
                System.out.println("javase");
                System.out.println("javaweb");
            }
            
        }
        
        class HeiMaStudent implements Coder {
            private Student s;                        //获取到被包装的类的引用
            public HeiMaStudent(Student s) {        //通过构造函数创建对象的时候,传入被包装的对象
                this.s = s;
            }
            @Override
            public void code() {                    //对其原有功能进行升级
                s.code();
                System.out.println("数据库");
                System.out.println("ssh");
                System.out.println("安卓");
                System.out.println(".....");
            }
            
        } 

 

使用指定的码表读写字符
* FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
* FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)

        BufferedReader br =                                     //高效的用指定的编码表读
                new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));
        BufferedWriter bw =                                     //高效的用指定的编码表写
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));
        int ch;
        while((ch = br.read()) != -1) {
            bw.write(ch);
        }
        
        br.close();
        bw.close();


转换流图解
* 画图分析转换流

获取文本上字符出现的次数
* 获取一个文本上每个字符出现的次数,将结果写在times.txt上

试用版软件
* 当我们下载一个试用版软件,没有购买正版的时候,每执行一次就会提醒我们还有多少次使用机会用学过的IO流知识,模拟试用版软件,试用10次机会,执行一次就提示一次您还有几次机会,如果次数到了提示请购买正版

递归
* 5的阶乘    

public static int fun(int num) {
        if(num == 1) {
            return 1;
        }else {
            return num * fun(num - 1);
        }

 

练习
* 需求:从键盘输入接收一个文件夹路径,打印出该文件夹下所有的.java文件名

public static File getDir() {
        Scanner sc = new Scanner(System.in);                //创建键盘录入对象
        System.out.println("请输入一个文件夹路径");
        while(true) {
            String line = sc.nextLine();                    //将键盘录入的文件夹路径存储
            File dir = new File(line);                        //封装成File对象
            if(!dir.exists()) {
                System.out.println("您录入的文件夹路径不存在,请重新录入");
            }else if(dir.isFile()) {
                System.out.println("您录入的是文件路径,请重新录入文件夹路径");
            }else {
                return dir;
            }
        }

}

public static void printJavaFile(File dir) {
        //1,获取到该文件夹路径下的所有的文件和文件夹,存储在File数组中
        File[] subFiles = dir.listFiles();
        //2,遍历数组,对每一个文件或文件夹做判断
        for (File subFile : subFiles) {
            //3,如果是文件,并且后缀是.java的,就打印
            if(subFile.isFile() && subFile.getName().endsWith(".java")) {
                System.out.println(subFile);
            //4,如果是文件夹,就递归调用
            }else if (subFile.isDirectory()){
                printJavaFile(subFile);
            }
        }
    }

 

序列流)(了解)
* 1.什么是序列流
    * 序列流可以把多个字节输入流整合成一个, 从序列流中读取数据时, 将从被整合的第一个流开始读, 读完一个之后继续读第二个, 以此类推.
* 2.使用方式
    * 整合两个: SequenceInputStream(InputStream, InputStream)
    * 
            FileInputStream fis1 = new FileInputStream("a.txt");            //创建输入流对象,关联a.txt
            FileInputStream fis2 = new FileInputStream("b.txt");            //创建输入流对象,关联b.txt
            SequenceInputStream sis = new SequenceInputStream(fis1, fis2);    //将两个流整合成一个流
            FileOutputStream fos = new FileOutputStream("c.txt");            //创建输出流对象,关联c.txt
            
            int b;
            while((b = sis.read()) != -1) {                                    //用整合后的读
                fos.write(b);                                                //写到指定文件上
            }
            
            sis.close();
            fos.close(); 
序列流整合多个(了解)
* 整合多个: SequenceInputStream(Enumeration)

        FileInputStream fis1 = new FileInputStream("a.txt");    //创建输入流对象,关联a.txt
        FileInputStream fis2 = new FileInputStream("b.txt");    //创建输入流对象,关联b.txt
        FileInputStream fis3 = new FileInputStream("c.txt");    //创建输入流对象,关联c.txt
        Vector<InputStream> v = new Vector<>();                    //创建vector集合对象
        v.add(fis1);                                            //将流对象添加
        v.add(fis2);
        v.add(fis3);
        Enumeration<InputStream> en = v.elements();                //获取枚举引用
        SequenceInputStream sis = new SequenceInputStream(en);    //传递给SequenceInputStream构造
        FileOutputStream fos = new FileOutputStream("d.txt");
        int b;
        while((b = sis.read()) != -1) {
            fos.write(b);
        }
    
        sis.close();
        fos.close();

内存输出流*****(掌握)
* 1.什么是内存输出流
    * 该输出流可以向内存中写数据, 把内存当作一个缓冲区, 写出之后可以一次性获取出所有数据
* 2.使用方式
    * 创建对象: new ByteArrayOutputStream()
    * 写出数据: write(int), write(byte[])
    * 获取数据: toByteArray()
    * 
            FileInputStream fis = new FileInputStream("a.txt");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int b;
            while((b = fis.read()) != -1) {
                baos.write(b);
            }
            
            //byte[] newArr = baos.toByteArray();                //将内存缓冲区中所有的字节存储在newArr中
            //System.out.println(new String(newArr));
            System.out.println(baos);
            fis.close();
内存输出流之黑马面试题(掌握)
* 定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)

            FileInputStream fis = new FileInputStream("a.txt");                //创建字节输入流,关联a.txt
            ByteArrayOutputStream baos = new ByteArrayOutputStream();        //创建内存输出流
            byte[] arr = new byte[5];                                        //创建字节数组,大小为5
            int len;
            while((len = fis.read(arr)) != -1) {                            //将文件上的数据读到字节数组中
                baos.write(arr, 0, len);                                    //将字节数组的数据写到内存缓冲区中
            }
            System.out.println(baos);                                        //将内存缓冲区的内容转换为字符串打印
            fis.close();
随机访问流概述和读写数据(了解)
* A:随机访问流概述
    * RandomAccessFile概述
    * RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
    * 支持对随机访问文件的读取和写入。

* B:read(),write(),seek()
    
对象操作流ObjecOutputStream(了解)
* 1.什么是对象操作流
    * 该流可以将一个对象写出, 或者读取一个对象到程序中. 也就是执行了序列化和反序列化的操作.
* 2.使用方式
    * 写出: new ObjectOutputStream(OutputStream), writeObject()

            public class Demo3_ObjectOutputStream {
    
                /**
                 * @param args
                 * @throws IOException 
                 * 将对象写出,序列化
                 */
                public static void main(String[] args) throws IOException {
                    Person p1 = new Person("张三", 23);
                    Person p2 = new Person("李四", 24);
            //        FileOutputStream fos = new FileOutputStream("e.txt");
            //        fos.write(p1);
            //        FileWriter fw = new FileWriter("e.txt");
            //        fw.write(p1);
                    //无论是字节输出流,还是字符输出流都不能直接写出对象
                    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e.txt"));//创建对象输出流
                    oos.writeObject(p1);
                    oos.writeObject(p2);
                    oos.close();
                }
            
            }
对象操作流ObjectInputStream(了解)
* 读取: new ObjectInputStream(InputStream), readObject()
    * 
            public class Demo3_ObjectInputStream {

                /**
                 * @param args
                 * @throws IOException 
                 * @throws ClassNotFoundException 
                 * @throws FileNotFoundException 
                 * 读取对象,反序列化
                 */
                public static void main(String[] args) throws IOException, ClassNotFoundException {
                    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e.txt"));
                    Person p1 = (Person) ois.readObject();
                    Person p2 = (Person) ois.readObject();
                    System.out.println(p1);
                    System.out.println(p2);
                    ois.close();
                }
            
            }
    
对象操作流优化(了解)
* 将对象存储在集合中写出

    Person p1 = new Person("张三", 23);
    Person p2 = new Person("李四", 24);
    Person p3 = new Person("马哥", 18);
    Person p4 = new Person("辉哥", 20);
    
    ArrayList<Person> list = new ArrayList<>();
    list.add(p1);
    list.add(p2);
    list.add(p3);
    list.add(p4);
    
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("f.txt"));
    oos.writeObject(list);                                    //写出集合对象
    
    oos.close();
* 读取到的是一个集合对象

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("f.txt"));
            ArrayList<Person> list = (ArrayList<Person>)ois.readObject();    //泛型在运行期会被擦除,索引运行期相当于没有泛型
        //想去掉黄色可以加注解            
        @SuppressWarnings("unchecked")
            for (Person person : list) {
                System.out.println(person);
            }
        
        ois.close();
加上id号(了解)
* 注意
    * 要写出的对象必须实现Serializable接口才能被序列化
    * 不用必须加id号

数据输入输出流(了解)
* 1.什么是数据输入输出流
    * DataInputStream, DataOutputStream可以按照基本数据类型大小读写数据
    * 例如按Long大小写出一个数字, 写出时该数据占8字节. 读取的时候也可以按照Long类型读取, 一次读取8个字节.
* 2.使用方式
    * DataOutputStream(OutputStream), writeInt(), writeLong() 

            DataOutputStream dos = new DataOutputStream(new FileOutputStream("b.txt"));
            dos.writeInt(997);
            dos.writeInt(998);
            dos.writeInt(999);
            
            dos.close();
    * DataInputStream(InputStream), readInt(), readLong()

            DataInputStream dis = new DataInputStream(new FileInputStream("b.txt"));
            int x = dis.readInt();
            int y = dis.readInt();
            int z = dis.readInt();
            System.out.println(x);
            System.out.println(y);
            System.out.println(z);
            dis.close();

打印流的概述和特点(掌握)
* 1.什么是打印流
    * 该流可以很方便的将对象的toString()结果输出, 并且自动加上换行, 而且可以使用自动刷出的模式
    * System.out就是一个PrintStream, 其默认向控制台输出信息

            PrintStream ps = System.out;
            ps.println(97);                    //其实底层用的是Integer.toString(x),将x转换为数字字符串打印
            ps.println("xxx");
            ps.println(new Person("张三", 23));
            Person p = null;
            ps.println(p);                    //如果是null,就返回null,如果不是null,就调用对象的toString()
* 2.使用方式
    * 打印: print(), println()
    * 自动刷出: PrintWriter(OutputStream out, boolean autoFlush, String encoding) 
    * 打印流只操作数据目的

            PrintWriter pw = new PrintWriter(new FileOutputStream("g.txt"), true);
            pw.write(97);
            pw.print("大家好");
            pw.println("你好");                //自动刷出,只针对的是println方法
            pw.close();

标准输入输出流概述和输出语句
* 1.什么是标准输入输出流(掌握)
    * System.in是InputStream, 标准输入流, 默认可以从键盘输入读取字节数据
    * System.out是PrintStream, 标准输出流, 默认可以向Console中输出字符和字节数据
* 2.修改标准输入输出流(了解)
    * 修改输入流: System.setIn(InputStream)
    * 修改输出流: System.setOut(PrintStream)
    * 
            System.setIn(new FileInputStream("a.txt"));                //修改标准输入流
            System.setOut(new PrintStream("b.txt"));                //修改标准输出流
            
            InputStream in = System.in;                                //获取标准输入流
            PrintStream ps = System.out;                            //获取标准输出流
            int b;
            while((b = in.read()) != -1) {                            //从a.txt上读取数据
                ps.write(b);                                        //将数据写到b.txt上
            }
            
            in.close();
            ps.close();

修改标准输入输出流拷贝图片(了解)
        System.setIn(new FileInputStream("IO图片.png"));        //改变标准输入流
        System.setOut(new PrintStream("copy.png"));         //改变标准输出流
        
        InputStream is = System.in;                            //获取标准输入流
        PrintStream ps = System.out;                        //获取标准输出流
        
        int len;
        byte[] arr = new byte[1024 * 8];
        
        while((len = is.read(arr)) != -1) {
            ps.write(arr, 0, len);
        }
        
        is.close();
        ps.close();
两种方式实现键盘录入(了解)
* A:BufferedReader的readLine方法。
    * BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
* B:Scanner


Properties的概述和作为Map集合的使用(了解)
* A:Properties的概述
    * Properties 类表示了一个持久的属性集。
    * Properties 可保存在流中或从流中加载。
    * 属性列表中每个键及其对应值都是一个字符串。 
* B:案例演示
    * Properties作为Map集合的使用
    
(Properties的特殊功能使用(了解)
* A:Properties的特殊功能
    * public Object setProperty(String key,String value)
    * public String getProperty(String key)
    * public Enumeration<String> stringPropertyNames()
* B:案例演示
    * Properties的特殊功能


    
Properties的load()和store()功能(了解)
* A:Properties的load()和store()功能
* B:案例演示
    * Properties的load()和store()功能

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值