• IO概述、异常、File文件类_DAY19


    IO概述:

        操作数据的工具

        IO流,即数据流,数据像水流一样通过IO工具进行传输。

        程序  <IO>   硬盘    

        绝对路径与相对路径

    1:异常(理解)

        (1)就是程序的非正常情况。

           异常相关操作:

               创建异常对象(JDK已定义的异常会自动创建对象,自定义异常需要手动创建)

               抛出异常(JDK已有定义的异常会自动抛出异常,自定义异常需要手动抛出)

           处理异常:

               程序员在有异常抛出时,异常的处理方法有两种:(1)将异常捕获并处理(2)声明抛出异常

        (2)异常的继承体系结构:

           Throwable:

               |--Error 严重的问题,不需要处理的。

               |--Exception 非RuntimeException必须进行处理。两种方案,点击鼠标即可。

                  |--RuntimeException 运行时期异常,需要修正代码。

        (3)jvm的默认处理方式:

           默认情况下,jvm会采用默认处理方案:

               把异常的全路径名称,原因,及位置等信息显示出来。

           注意:

               如果是jvm的默认处理方式,那么,它会在出问题的地方结束。

        (4)我们自己的处理方案:

           A:处理方式之一:使用捕获

           try...catch...finally

               基本格式:

                  try {

                      可能有问题的代码;

                  }catch(异常对象) {

                      对问题的处理;

                  }finally {   //一定会执行的代码

                      释放资源;

                  }

               变形格式:

                  try...catch

                  try...catch...catch

                  try...catch...catch...finally

                  try...finally

               多异常处理方式:

                  分别捕获分别处理,每个try对应一个catch  (  cn.itcast2.demo4)

    package cn.itcast2;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /*
     * 多个异常的捕获处理:
     *         1:分别捕获分别处理,每个try对应一个catch
     */
    public class Demo4 {
    
        public static void main(String[] args) {
    
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            try {
                Date parse = df.parse("2008-08-08");
                System.out.println(parse);
            } catch (ParseException e) {
                System.out.println("您的日期格式有误,请换成2008-08-08的格式!");
            }
            
            int a = 10;
            int b = 0;   
            try {
                System.out.println(a/b);
            } catch (Exception e) {
                System.out.println("您的计算中,有数学错误,请更换数字");
            }
            
            System.out.println("================");
        }
    
    }
    View Code2

                  分别捕获分别处理,一个try对应所有catch  (cn.itcast2.demo5)  ,注意:大的异常不能在前边捕获

    package cn.itcast2;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /*
     * 多个异常的捕获处理:
     *         2:分别捕获分别处理,一个try对应所有catch,注意:前边的异常一定要小于后边的异常
     *         3:一次捕获共同处理,不能同时捕获大的异常与小的异常
     */
    public class Demo5 {
    
        public static void main(String[] args) {
    
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            int a = 10;
            int b = 0;   
            
            //2:格式2
                    //报错,前边的异常不小于后边的异常
    //        try {
    //            Date parse = df.parse("2008,08-08");
    //            System.out.println(parse);
    //            System.out.println(a/b);
    //        } catch (ParseException e) {
    //            System.out.println("您的日期格式有误,请换成2008-08-08的格式!");
    //        } catch (ArithmeticException e) {
    //            System.out.println("您的计算中,有数学错误,请更换数字");
    //        }
            
            try {
                Date parse = df.parse("2008,08-08");
                System.out.println(parse);
                System.out.println(a/b);
                    //前边的异常一定要小于后边的异常
            } catch (ParseException e) {
                System.out.println("您的日期格式有误,请换成2008-08-08的格式!");
            } catch (Exception e) {
                System.out.println("您的计算中,有数学错误,请更换数字");
            } 
            
            System.out.println("try后的代码继续执行...");
            
            
            //格式3:
            try{
                Date parse = df.parse("2008-08-08");
                System.out.println(parse);
                System.out.println(a/b);
            }catch(ParseException|ArithmeticException e) {  //一次捕获共同处理,不能同时捕获大的异常与小的异常
                System.out.println(e);
            }
            
            System.out.println(true||false);
            System.out.println(true|false);
        }
    }
    View Code

                  一次捕获共同处理

                         注意:不能同时捕获大的异常与小的异常

               注意:

                  如果多个异常,有子父关系,父异常一定要放在最后。

                  如果多个异常,是平级关系,它们存在的位置没有顺序关系。

                  执行顺序:

                      在try里面的代码会按照从上往下执行,一旦发生问题,

                      就会产生一个异常对象,去和catch里面进行匹配。

                      有对应的匹配,就走对应的处理方案。

                      没有,就找父匹配,有就走对应的处理方案。

                      如果找不到,那么就由jvm采用默认处理方案。

               JDK7的新特性:在处理多个平级的异常的时候

                  catch(ExceptionA | ExceptionB | ExceptionC ... e) {

                 

                  }

           B:异常处理方式之二:使用声明抛出

           throws

     *         throws:用于声明函数抛出异常。用于函数声明。

     *         多个异常可以同时声明抛出,用逗号分隔。  (cn.itcast2.demo7)

    package cn.itcast2;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    
    /*
     * 异常处理方式:声明异常抛出
     * throws:用于声明函数抛出异常。用于函数声明。
     *             是异常对象的处理方式之一。
     *             多个异常可以同时声明抛出,用逗号分隔。
     */
    public class Demo7 {
        
        public static void main(String[] args) {
            int a = 10,b=0;
            try {
                method(a,b);
            } catch (ArithmeticException e) {
                e.printStackTrace();
            }
            System.err.println("--------------");
            
            try {
                method2(a,b);
            } catch (ArithmeticException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }
            System.err.println("--------------");
        }
        
        public static void method(int a,int b) throws ArithmeticException{
            System.err.println(a/b);
        }
        
        public static void method2(int a,int b) throws ArithmeticException, ParseException{ //多个异常可以同时声明抛出,用逗号分隔
            method(a,b);
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            df.parse("a");
        }
    
    }
    
    
    /**  程序执行结果
    java.lang.ArithmeticException: / by zero
        at cn1.Demo7.method(Demo7.java:35)
        at cn1.Demo7.main(Demo7.java:18)
    --------------
    java.lang.ArithmeticException: / by zero
        at cn1.Demo7.method(Demo7.java:35)
        at cn1.Demo7.method2(Demo7.java:39)
        at cn1.Demo7.main(Demo7.java:25)
    --------------
    */
    View Code

        (5)自定义异常

           如果涉及其他需求,JDK没有提供相应的异常对象,则可以自己定义异常。

           定义格式:继承Exception或者RuntimeException。同时需要带参的构造方法,用于接收异常信息。

           public class MyException extends Exception{

               public MyException(String message){

                  super(message);

               }

           }

           例子:cn.itcast2.demo8   cn.itcast2.MyException.java

    package cn.itcast2;
    /*
     * 自定义异常:
     *         补充java没有提供的异常类
     */
    public class Demo8 {
    
        public static void main(String[] args) {
    
            //规定,一个班最多只能有100个人。
            int classNumber = 101;
            
                   //方式一:捕获异常
            if(classNumber>100) {
                try {
                    throw new MyException("班级人数大于100了,不能大于100!");//手动抛出自定义异常类对象
                } catch (MyException e) {
                    System.err.println("=======");
                    System.err.println(e.getMessage()+".........");
                    e.printStackTrace();
                    System.err.println("=======");
                }
            }
            
            System.err.println("-------------");
            
            try {
                method();
            } catch (MyException e) {
                e.printStackTrace();
            }
            
        }
    
        //方式二:声明抛出异常
        public static void method() throws MyException { //声明抛出异常
            //规定,一个班最多只能有100个人。
            int classNumber = 101;
            
            if(classNumber>100) {
                throw new MyException("班级人数大于100了,不能大于100!");//手动抛出自定义异常类对象
            }
            
            System.err.println("-------------");
        }
    }
    View Code
    package cn.itcast2;
    /*
     * 自定义异常:超过100就不行
     */
    public class MyException extends Exception {
    
        public MyException(String message) {
            super(message);
        }
    
    }
    View Code

        (6)面试题:

           A:Exception和RuntimeException的区别?

               Exception:分为编译期异常和运行期异常。编译期异常是必须处理的。否则,代码不能编译通过。

               RuntimeException:运行期异常,不需要编写异常处理代码,但是可能需要修正程序参数或者逻辑代码。

           B:throws和throw的区别?

               throws:在方法声明上,后面跟的是异常类名。

                      throws声明后面如果是一个运行时期异常,调用者不需要处理。这种方式没有意义。

                      throws声明后面跟的是一个编译期异常,调用者是必须处理的。

               throw:在方法体中,后面跟的是异常对象名。

                      throw后面如果抛出的是运行时期异常对象,那么方法上是不需要进行声明的。

                      throw后面如果抛出的是编译时期异常对象,那么,一般在方法声明上都是要用throws声明该方法有异常。

           C:finally的面试题

               a:final,finally,finalize的特点及区别?

                  final:最终的意思,可以修饰类,成员变量,成员方法

                      修饰类,类不能被继承

                      修饰变量,变量是常量

                      修饰方法,方法不能被重写

                  finally:是异常处理的一部分,用于释放资源。

                         一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了

                  finalize:是Object类的一个方法,用于垃圾回收

               b:如果catch里面有return,请问finally里面的代码还执行吗?

                 如果执行,是在return前,还是后呢?

                 会执行,在前,确切的说在中间,先执行return的代码,再执行finally里面的代码,最后return

               c:写一个程序,测试finally里面的操作对结果没有影响。

                  finally一般只用于释放资源。cn.itcast.demo9

           D:jvm的默认处理方式? 打印,宕机

        (7)对于异常,怎么选择呢?

           A:能够自己处理的时候,尽量自己处理。

           B:在方法里面尽量不要抛。

           C:将来在实际开发中,我们会把不同的异常给出不同的界面进行显示给用户。

        (8)子父关系中的异常处理?

           class Fu {

               public void show()  throws Exception  {

               }

           }

           class Zi extends Fu {

               public void show() throws RuntimeException {

               }

           }

           class Demo {

               public static void main(String[] args) {

               }

           }

           子的重写方法中不能抛出比父更大的异常。

    2:File(理解)

        (1)因为硬盘上对数据的存储基本上都是以文件存在。为了方便对文件或者文件夹进行操作。

           java就提供了一个类File供我们使用。本质上是对路径的封装。

        (2)File类构造方法:

           A:File file = new File("d:\a.txt");

           B:File file = new File("d:\","a.txt");

           C:File file = new File("d:");

             File file2 = new File(file,"a.txt");

           以上三种格式等价。

        (3)File类的功能:

           A:创建功能

               创建文件:createNewFile()

               创建文件夹:mkdir(),mkdirs()

               例子:cn.itcast3.demo2

    package cn.itcast3;
    
    import java.io.File;
    import java.io.IOException;
    
    /*
     * File类的普通方法:
     *         1:public boolean createNewFile() throws IOException 创建文件
     *         2:public boolean mkdir()  创建文件夹
     *                 注意:现有文件夹,后有文件
     *         3:public boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。  将所有父目录全部创建。
     */
    public class Demo2 {
    
        public static void main(String[] args) throws IOException {
            //创建文件夹与文件对象
            File dir = new File("z");
            File file = new File("z/z.txt");
            
            //2:创建文件夹z
            boolean mkdir = dir.mkdir();
            System.out.println(mkdir);
            //1:创建文件z.text
            boolean createNewFile = file.createNewFile();
            System.out.println(createNewFile);
            
            //层级创建文件
            File dir2 = new File("c/a/d/e/w/d/f/t/z");
            boolean mkdir2 = dir2.mkdirs();
            System.out.println(mkdir2);
        }
    
    }
    View Code

               注意:仅仅根据后缀名并不能判断是文件还是文件夹。

           B:删除功能

               删除文件或者文件夹:delete()

               注意:

                  A:删除一个带内容的目录,必须先删除内容,在删除目录。

                  B:java中的删除不走回收站。

           C:判断功能

               判断file是否存在:exists()

               判断file是否是文件:isFile()

               判断file是否是文件夹:isDirectory()

               例子:cn.itcast3.demo3-myself.text

    import java.io.File;
    import java.io.IOException;
    
    
    /*
     *  File类的普通方法:
     *      1:public boolean delete()  文件可以直接删除,文件夹删除时,必须保证里边已经没有内容了
     *      2:public boolean isHidden()测试此抽象路径名指定的文件是否是一个隐藏文件
     *      3:public boolean isFile()  判断是否是文件
     *      4:public boolean isDirectory() 判断是否是文件夹
     *      5:public boolean exists()  测试此抽象路径名表示的文件或目录是否存在。
     */
    public class Demo3 {
    
        public static void main(String[] args) throws IOException {
            //创建文件夹
            File dir = new File("b");
            dir.mkdir();
    
            //需要先创建文件夹,然后创建文件
            File file = new File("b/b.txt");
            file.createNewFile();
    
         /*   //先删除文件,再删除文件夹
            System.out.println(file.delete());
            System.out.println(dir.delete());*/
    
            //是否是隐藏文件
            System.out.println(file.isHidden());
    
            //是否是文件
            System.out.println(file.isFile());
    
            //是否是文件夹
            System.out.println(dir.isDirectory());
    
            // 测试此抽象路径名表示的文件或目录是否存在。
            System.out.println(file.exists());
    
        }
    
    }
    View Code

           D:重名名功能

               把旧名称改变为新名称:renameTo()

                  注意:路径问题。

               重命名涉及两个File对象。

               将File1重命名成File2

                  在同一目录下:

                      file2文件已经存在,重命名失败

                      file2文件不存在,重命名成功

                  在不同目录下:

                      file2文件已经存在,重命名失败

                      file2文件不存在,剪切成功

               例子:cn.itcast3.demo4

    package cn.itcast3;
    
    import java.io.File;
    
    /*
     * File类的普通方法:
     *         public boolean renameTo(File dest)  同目录:重命名/不同目录:剪切加重命名
     */
    public class Demo4 {
    
        public static void main(String[] args) {
    
            File file = new File("a.txt");
            File file2 = new File("b.txt");
            File file3 = new File("d/c.txt");
            
            boolean renameTo = file.renameTo(file2);
            System.out.println(renameTo);
            
            boolean renameTo2 = file2.renameTo(file3);
            System.out.println(renameTo2);
        }
    
    }
    View Code

           E:获取功能

               基本获取

                  获取绝对路径:getAbsolutePath()

                  获取相对路径:getPath()

                  获取名称:getName()

                  获取大小:length()  //英文字母1个字节,中文字母两个字节

                  获取最后修改时间:lastModified()

                  例子:cn.itcast3.demo5

    package cn.itcast3;
    
    import java.io.File;
    import java.util.Date;
    
    /*
     * File类的普通方法:
     *     1:public String getAbsolutePath() : 返回此抽象路径名的绝对路径名字符串。
     *     2:public String getPath(): 将此抽象路径名转换为一个路径名字符串。
     *     3:public String getParent():返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
     *     4:public File getParentFile():返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。
     *     5:public String getName():返回由此抽象路径名表示的文件或目录的名称。
     *     6:public long length()  返回:文件存储内容的长度
     *     7:public long lastModified():返回上一次修改时间毫秒值
     */
    public class Demo5 {
    
        public static void main(String[] args) {
    
            File file = new File("a.txt");
            File file2 = new File("D:/Lesson/JAVA/JAVA基础/北京/150315/day19/code/day19/a.txt");
            //1
            System.out.println(file.getAbsolutePath());
            System.out.println(file2.getAbsolutePath());
            System.out.println("===========");
            //2
            System.out.println(file.getPath());
            System.out.println(file2.getPath());
            System.out.println("===========");
            
            //3
            String p = file.getParent();
            System.out.println(p);
            String p2 = file2.getParent();
            System.out.println(p2);
            System.out.println("===========");
            //4
            File pFile = file.getParentFile();
            System.out.println(pFile);
            File pFile2 = file2.getParentFile();
            System.out.println(pFile2);
            System.out.println("===========");
            //5
            String name = file.getName();
            System.out.println(name);
            String name2 = file2.getName();
            System.out.println(name2);
            System.out.println("===========");
            
            //6
            System.out.println(file.length());
            
            //7
            System.out.println(file.lastModified());//返回毫秒值1428829519158L
            System.out.println(new Date(file.lastModified()));//返回日期格式
        }
    
    }
    View Code

               高级获取

                  获取指定目录下所有文件或者文件夹的名称数组:list()

                  获取指定目录下所有文件或者文件夹的File数组:listFiles()

                  返回所有盘符:listRoots()

                  例子1:cn.itcast3.demo6

    package cn.itcast3;
    
    import java.io.File;
    import java.util.Arrays;
    
    /*
     * 文件高级获取:
     *     1:public static File[] listRoots() 获取所有盘符的文件对象
     *     2:public String[] list() 这些字符串指定此抽象路径名表示的目录中的文件和目录。即该File下的所有文件及目录(字符串)。
     *     3:public File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 即File下的所有文件及目录(File对象)。
     */
    public class Demo6 {
    
        public static void main(String[] args) {
            //1:
            File[] listRoots = File.listRoots();
            System.out.println(Arrays.toString(listRoots));
            
            //2:
            File dir = new File("src/cn/itcast");
            
            String[] list = dir.list();
            System.out.println(Arrays.toString(list));
            
            //3:
            File[] listFiles = dir.listFiles();
            System.out.println(Arrays.toString(listFiles));
            
            for (File file : listFiles) {
                System.out.println(file.getName());
            }
        }
    
    }
    View Code

                  例子2:cn.itcast3.demo7:获取srccnitcast目录下所有.java结尾的文件(注意是文件 ,不是文件夹)

    package cn.itcast3;
    
    import java.io.File;
    
    /*
     * 获取srccnitcast目录下所有.java结尾的文件
     */
    public class Demo7 {
    
        public static void main(String[] args) {
    
            //创建文件对象,表示指定的文件夹
            File dir = new File("src/cn/itcast");
    
                   //方法一:(如果有文件夹是.java结尾的,则不能过滤该文件夹)
    //        //获取该文件夹下的所有File对象字符串表现(文件,文件夹)
    //        String[] list = dir.list();
    //        //获取该数组中的每一个元素
    //        for (String fileordir : list) {
    //            boolean endsWith = fileordir.endsWith(".java");
    //            if(endsWith) {
    //                System.out.println(fileordir);
    //            }
    //        }
    
            //方法二:
            //获取该文件夹下的所有File对象对象表现(文件,文件夹)
             File[] listFiles = dir.listFiles();
             
             //获取该数组中的每一个元素
             for (File fileordir : listFiles) {
                //先判断是否为文件
                 if(fileordir.isFile()) {
                        boolean endsWith = fileordir.getName().endsWith(".java");
                        if(endsWith) {
                            System.out.println(fileordir.getName());
                        }
                 }
            }
        }
    
    }
    View Code

                  文件过滤器:

                      接口 FilenameFilter  重写accept()方法 

                      方式1,定义类实现FilenameFilter,然后用file.list(该类的实例对象) 

                      方式2,匿名内部类

                  例子:cn.itcast3.demo8

    package cn.itcast3;
    
    import java.io.File;
    import java.io.FilenameFilter;
    import java.util.Arrays;
    
    /*
     * File的方法:
     *         public String[] list(FilenameFilter filter)
     *         public File[] listFiles(FilenameFilter filter)
     * //        3:public File(File parent,String child)
     * 文件过滤器
     *         FilenameFilter:
     *         boolean accept(File dir, String name)  将list/listFiles方法所在目录下所有的File对象都判断一次是否符合条件。符合条件返回true,不符合,返回false
     *         
     * 获取srccnitcast目录下所有.java结尾的文件,要求使用过滤器
     */
    public class Demo8 {
    
        public static void main(String[] args) {
    
            //创建文件对象,表示指定的文件夹
            File dir = new File("src/cn/itcast");
            
            //获取该文件夹下的所有符合条件的File对象字符串表现(文件,文件夹)
            String[] list = dir.list(new FilenameFilter(){   //匿名内部类
                @Override
                public boolean accept(File dir, String name) {
                    File thisFile = new File(dir,name);
                    if(thisFile.isFile()){
                        if(name.endsWith(".java")) {
                            return true;
                        }
                    }
                    return false;
                }});
            
            System.out.println(Arrays.toString(list));
        }
    }
    View Code

     ---------------------------------------------------------------------------------------------------------------

    例子程序:

    1、返回某文件夹下所有以java结尾的文件

    a)使用list方法

    b)使用listFiles方法

    c)使用list方法加文件过滤器

     d)使用listFiles方法加文件过滤器

    import java.io.File;
    import java.io.FilenameFilter;
    import java.util.Arrays;
    
    /**
     * 7:返回某文件夹下所有以java结尾的文件。
     * a)使用list方法
     * b)使用listFiles方法
     * c)使用list方法加文件过滤器
     * d)使用listFiles方法加文件过滤器
     */
    public class Test7 {
        public static void main(String[] args) {
            //a)使用list方法  (不能判断是文件还是文件夹)
           /* File file=new File("src/cn1");
            String[] strings=file.list();
            for(String s:strings){
                if(s.endsWith(".java")){
                    System.out.println(s);
                }
            }*/
    
            //使用listFiles方法
           /* File file = new File("src/cn1");
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isFile()) {
                    if(f.getName().endsWith(".java")){
                        System.out.println(f.getName());
                    }
                }
            }*/
    
            //c)使用list方法加文件过滤器
           /* File file=new File("src/cn1");
            String[] strings=file.list(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    File file1=new File(dir,name);
                    if(file1.isFile()){
                        if(file1.getName().endsWith(".java")){
                            return true;
                        }
                    }
                    return false;
                }
            });
            System.out.println(Arrays.toString(strings));*/
    
            //d)使用listFiles方法加文件过滤器
            /*File file=new File("src/cn1");
            File[] files=file.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    File file1=new File(dir,name);
                    if(file1.isFile()){
                        if(file1.getName().endsWith(".java")){
                            return true;
                        }
                    }
                    return false;
                }
            });
            for(File f:files){
                System.out.println(f.getName());
            }*/
    
        }
    }
    View Code

    2、完成一个文件的创建,判断,删除。

    import java.io.File;
    import java.io.IOException;
    
    /**
     * 3:完成一个文件的创建,判断,删除。
     */
    public class Test3 {
        public static void main(String[] args) throws IOException {
            File file=new File("src/cn2/a.test");
            //文件的创建
            file.createNewFile();
            //判断
            System.out.println(file.isFile());
            System.out.println(file.isDirectory());
            //删除
            file.delete();
        }
    }
    View Code

    3、完成文件的创建、重命名、删除。

    import java.io.File;
    import java.io.IOException;
    
    /**
     * 5:完成文件的创建、重命名、删除。
     */
    public class Test5 {
        public static void main(String[] args) throws IOException {
            //文件的创建
            File file=new File("d.txt");
            file.createNewFile();
    
           //重命名
            File file1=new File("src/cn1/e.txt");
            file.renameTo(file1);
    
            //删除
             file1.delete();
        }
    }
    View Code

    4、完成多级目录的创建。

    import java.io.File;
    import java.io.IOException;
    
    /**
     * 6:完成多级目录的创建。
     */
    public class Test6 {
        public static void main(String[] args) throws IOException {
            File dir=new File("src/a/b/c/d/e");
            dir.mkdirs();
            File file=new File("src/a/a.txt");
            file.createNewFile();
        }
    
    }
    View Code
  • 相关阅读:
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    每日总结
    Windows邮件添加QQ邮箱
  • 原文地址:https://www.cnblogs.com/hezhiyao/p/7763812.html
Copyright © 2020-2023  润新知