异常和File
- 一、异常
- 1.1异常的分类
- 1.2 异常的作用
- 1.3 异常的处理方式
- 1.3.1 JVM默认的处理方式
- 1.3.2 自己处理(捕获异常)
- 1.3.3 自己处理(灵魂四问)
- 1.4 异常中的常见方法
- 1.5 抛出异常
- 综合练习(键盘录入数据)
- 1.6 自定义异常
- 二、File
- 2.1 路径
- 2.2 File的常见成员方法(判断、获取)
- 2.3 File的常见成员方法(创建、删除)
- 2.4 File的常见成员方法(获取并遍历)
- 三、综合练习
- 练习一:(创建文件)
- 练习二:(单个文件夹查找文件)
- 练习三:(遍历硬盘查找文件)
- 练习四:(删除文件夹)
- 练习五:(统计文件夹大小)
- 练习六:(统计各种文件数量)
一、异常
异常:异常就是代表程序出现的问题
1.1异常的分类
Error:代表的系统级别错误(属于严重问题)
- 系统一旦出现问题,sun公司会把这些错误封装成Error对象。
- Error是给sun公司自己用的,不是给我们程序员用的。
- 因此我们开发人员不用管它。
Exception:叫做异常,代表程序可能出现问题。
我们通常会用Exception以及他的子类来封装程序出现的问题。
运行时异常:RuntimeException及其子类,编译阶段不会出现异常提醒。
运行时出现的异常(如:数组索引越界异常)
编译时异常:编译阶段就会出现异常提醒的。(如:日期解析异常)
编译时异常:在编译阶段,必须要手动处理,否则代码报错
运行时异常:在编译阶段是不需要处理的,是代码运行时出现的异常
1.2 异常的作用
作用一:异常时用来查询bug的关键参考信息
作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
public static void main(String[] args) {Student s = new Student();//年龄在20-40之间s.setAge(50);}
Student类中setAge方法
/*** 设置** @param age*/public void setAge(int age) {if (age < 20 || age > 40){throw new RuntimeException("年龄在20-40岁之间");//运行时异常}else {this.age = age;}}
Exception in thread "main" java.lang.RuntimeException: 年龄在20-40岁之间at myException.Student.setAge(Student.java:49)at myException.ExceptionDemo1.main(ExceptionDemo1.java:7)
1.3 异常的处理方式
1.3.1 JVM默认的处理方式
- 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
- 程序停止执行,下面的代码不会再执行了
1.3.2 自己处理(捕获异常)
public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6};try {System.out.println(arr[10]);//此处出现了异常,程序就会在这里创建一个ArrayIndexOutOfBoundsException对象//new ArrayIndexOutOfBoundsException();//拿着这个对象到catch的小括号中对比,看括号中的变量是否可以接收这个对象//如果能被接收,就表示该异常就被捕获(抓住),执行catch里面对应的代码//当catch 里面所有的代码执行完毕,继续执行try...catch体系下面的其他代码}catch (ArrayIndexOutOfBoundsException e){System.out.println("索引越界了");}System.out.println("看看我执行了吗");}
好处:可以让程序继续往下执行,不会停止。
1.3.3 自己处理(灵魂四问)
- 灵魂一问:如果try中没有遇到问题,怎么执行?
- 会把try里面所有的代码全部执行完毕,不会执行catch里面的代码
- 注意:
- 只有当出现了异常才会执行catch里面的代码
- 灵魂二问:如果try中可能会遇到多个问题,怎么执行?
- 会写多个catch与之对应
- 细节:
- 如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面。
- 如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面。
public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6};try {System.out.println(arr[10]);System.out.println(2 / 0);String s = null;} catch (ArrayIndexOutOfBoundsException e) {System.out.println("索引越界了");} catch (ArithmeticException e) {System.out.println("除数不能为零!");} catch (NullPointerException e) {System.out.println("空指针异常");} catch (Exception e) {System.out.println("Exception");}System.out.println("看看我执行了吗");}
了解性:
- 在JDK7之后,我们可以在catch中同时捕获多个异常,中间用 | 进行隔开
- 表示如果出现了A异常或者B异常的话,采取同一种处理方案
-
灵魂三问:如果try中遇到的问题没有被捕获,怎么执行?
相当于try…catch的代码白写了,最终还是会交给虚拟机进行处理。 -
灵魂四问:如果try中遇到了问题,那么try下面的其他代码还会执行吗?
- 下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体
- 但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理。
1.4 异常中的常见方法
public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5, 6};try {System.out.println(arr[10]);} catch (ArrayIndexOutOfBoundsException e) {//0.返回此 throwable 的详细消息字符串/*String message = e.getMessage();System.out.println(message);*/ //Index 10 out of bounds for length 6//1.返回此可抛出的简短描述/*String string = e.toString();System.out.println(string);*/ //java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 6//2.把异常的错误信息输出在控制台e.printStackTrace();//仅仅是打印信息,不会停止程序运行}System.out.println("看看我执行了吗");}
拓展内容:
//正常的输出语句System.out.println(123);//错误的输出语句System.err.println(456); //字体颜色是红色
public void printStackTrace()
- 在底层时利用 System.err.println 进行输出
- 把异常的错误信息以红色字体输出在控制台
- 细节
- 仅仅是打印信息,不会停止程序运行
1.5 抛出异常
public static void main(String[] args) {//定义一个方法求数组的最大值
// int[] arr = {1,2,3,4,5};int[] arr = null;
// int[] arr = {};int max = 0;try {max = getMax(arr);} catch (NullPointerException e) {System.out.println("空指针异常");} catch (ArrayIndexOutOfBoundsException e){System.out.println("索引越界异常");}System.out.println(max);}public static int getMax(int[] arr) /*throws NullPointerException, ArrayIndexOutOfBoundsException*/ {if (arr == null) {//手动创建一个异常对象,并把这个异常交给方法的调用者处理//此时方法就会结束,下面的代码就不会执行了throw new NullPointerException();}if (arr.length == 0) {throw new ArrayIndexOutOfBoundsException();}int max = arr[0];for (int i = 1; i < arr.length; i++) {if (max < arr[i]) {max = arr[i];}}return max;}
综合练习(键盘录入数据)
需求:
- 键盘录入自己心仪的女朋友姓名和年龄,
- 姓名的长度在3~10之间
- 年龄的范围为18-40岁
- 超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。
提示: - 需要考虑用户在键盘录入时的所有情况。
- 比如:录入年龄时超出范围,录入年龄时录入了abc等情况
女朋友类:
package myException;public class GirlFriend {private String name;private int age;public GirlFriend() {}public GirlFriend(String name, int age) {this.name = name;this.age = age;}/*** 获取** @return name*/public String getName() {return name;}/*** 设置** @param name*/public void setName(String name) {//姓名的长度在3~10之间if (name.length() < 3 || name.length() > 10) {throw new RuntimeException();}this.name = name;}/*** 获取** @return age*/public int getAge() {return age;}/*** 设置** @param age*/public void setAge(int age) {//年龄的范围为18-40岁if (age < 18 || age > 40) {throw new RuntimeException();}this.age = age;}public String toString() {return "GirlFriend{name = " + name + ", age = " + age + "}";}
}
public static void main(String[] args) {/*需求:键盘录入自己心仪的女朋友姓名和年龄,姓名的长度在3~10之间年龄的范围为18-40岁超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。提示:需要考虑用户在键盘录入时的所有情况。比如:录入年龄时超出范围,录入年龄时录入了abc等情况*///键盘录入自己心仪的女朋友姓名和年龄Scanner sc = new Scanner(System.in);//创建女朋友对象GirlFriend gf = new GirlFriend();while (true) {try {//接收女朋友的姓名System.out.println("请输入你女朋友的姓名");String name = sc.nextLine();gf.setName(name);//接收女朋友的年龄System.out.println("请输入你女朋友的年龄");String ageStr = sc.nextLine();int age = Integer.parseInt(ageStr);gf.setAge(age);break;} catch (NumberFormatException e) {System.out.println("年龄格式错误,年龄格式必须是数字");} catch (RuntimeException e) {System.out.println("姓名的长度或者年龄的范围有误");}}//打印System.out.println(gf);}
1.6 自定义异常
技巧:
NameFormat:当前异常的名字,表示姓名格式化问题
Exception: 表示当前类是一个异常类运行时:RunTimeException 核心 就表示由于参数错误而导致的问题
编译时:Exception 核心 提醒程序员检查本地信息
姓名格式化异常:
package myException.Test2;public class NameFormatException extends RuntimeException{//技巧:// NameFormat:当前异常的名字,表示姓名格式化问题// Exception: 表示当前类是一个异常类//运行时:RunTimeException 核心 就表示由于参数错误而导致的问题//编译时:Exception 核心 提醒程序员检查本地信息public NameFormatException() {}public NameFormatException(String message) {super(message);}
}
年龄越界异常:
package myException.Test2;public class AgeOutOfBoundsException extends RuntimeException{public AgeOutOfBoundsException() {}public AgeOutOfBoundsException(String message) {super(message);}
}
public static void main(String[] args) {/*需求:键盘录入自己心仪的女朋友姓名和年龄,姓名的长度在3~10之间年龄的范围为18-40岁超出这个范围是异常数据不能赋值,需要重新录入,一直录到正确为止。提示:需要考虑用户在键盘录入时的所有情况。比如:录入年龄时超出范围,录入年龄时录入了abc等情况*///键盘录入自己心仪的女朋友姓名和年龄Scanner sc = new Scanner(System.in);//创建女朋友对象myException.Test1.GirlFriend gf = new GirlFriend();while (true) {try {//接收女朋友的姓名System.out.println("请输入你女朋友的姓名");String name = sc.nextLine();gf.setName(name);//接收女朋友的年龄System.out.println("请输入你女朋友的年龄");String ageStr = sc.nextLine();int age = Integer.parseInt(ageStr);gf.setAge(age);break;} catch (NumberFormatException e) {e.printStackTrace();} catch (NameFormatException e) {e.printStackTrace();} catch (AgeOutOfBoundsException e) {e.printStackTrace();}}//打印System.out.println(gf);}
二、File
2.1 路径
- File对象就表示一个路径,可以是文件的路径、也可以是文件夹的路径
- 这个路径可以是存在的,也允许是不存在的
public static void main(String[] args) {//0.根据文件路径创建文件对象// 根据字符串表示的路径,变成File对象String str = "G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt";File f1 = new File(str);System.out.println(f1);//1.根据路径名字字符串和子路径名字字符串创建文件对象//父级路径:G:\code\Java\basic_code\day27_code\src\myFile//子级路径:a.txtString parent = "G:\\code\\Java\\basic_code\\day27_code\\src\\myFile";String child = "a.txt";File f2 = new File(parent, child);System.out.println(f2);File f3 = new File(parent + "//" + child);System.out.println(f3);//2.根据父路径对应文件对象和子路径名字字符串创建文件对象//把一个File表示的路径和String表示路径进行拼接File parent2 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile");String str2 = "a.txt";File f4 = new File(parent2, str2);System.out.println(f4);}
2.2 File的常见成员方法(判断、获取)
- 判断
public static void main(String[] args) {//0.对一个文件的路径进行判断File f1 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt");System.out.println(f1.isDirectory()); //falseSystem.out.println(f1.isFile()); // trueSystem.out.println(f1.exists()); // trueSystem.out.println("======================");//1.对一个文件夹的路径进行判断File f2 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile");System.out.println(f2.isDirectory()); //trueSystem.out.println(f2.isFile()); // falseSystem.out.println(f2.exists()); // true}
- 获取
public static void main(String[] args) {//0.返回文件的大小,字节数量//细节1:这个方法只能获取文件的大小,单位是字节//如果单位我们要是M,G,可以不断的除以1024//细节2:这个方法无法获取文件夹的大小//如果我们要获取一个文件夹的大小,需要把这个文件夹里面所有的文件大小都累加在一起File f1 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt");long len = f1.length();System.out.println(len);System.out.println("---------------------");//1.返回文件的绝对路径File f2 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt");File path1 = f2.getAbsoluteFile();System.out.println(path1);File f3 = new File("day27_code//src//myFile//a.txt");File path2 = f3.getAbsoluteFile();System.out.println(path2);System.out.println("---------------------------------");//2.返回定义文件时使用的路径File f4 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt");String path3 = f4.getPath();System.out.println(path3);File f5 = new File("day27_code//src//myFile//a.txt");String path4 = f5.getPath();System.out.println(path4);System.out.println("------------------------------");//3.获取文件的名字/*细节1:* 返回文件的文件名 后缀名、扩展名** 细节2:* 文件夹:返回的就是文件夹的名字*/File f6 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt");String name = f6.getName();System.out.println(name);File f7 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile");String name2 = f7.getName();System.out.println(name2);//4.返回文件的最后修改时间File f8 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile");long time = f8.lastModified();System.out.println(time); //获取的是毫秒值}
2.3 File的常见成员方法(创建、删除)
public static void main(String[] args) throws IOException {//0.创建一个新的空的文件/*细节1:如果当前路径表示的文件是不存在的,则创建成功,方法返回false* 如果当前路径表示的文件是存在的,则回创建失败,方法返回false* 细节2:如果父级路径是不存在的,那么方法会有异常IOException* 细节3:createNewFile方法创建的一定是文件,如果路径中不包含后缀名,则创建一个没有后缀的文件*/File f1 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\b.txt");boolean b = f1.createNewFile();System.out.println(b);//1.创建单级文件夹/*细节1:Windows当中路径是唯一的,如果当前路径已经存在,则创建失败,返回false* 细节2:mkdir方法只能创建单级文件夹,无法创建多级文件夹*/File f2 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\aaa");boolean b2 = f2.mkdir();System.out.println(b2);//2.创建多级文件夹//细节:既可以创建单级的,又可以创建多级的文件夹File f3 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\aaa\\bbb\\ccc");boolean b3 = f3.mkdirs();System.out.println(b3);//3.删除/*细节:* 如果删除的是文件,则直接删除,不走回收站。* 如果删除的是空文件夹,则直接删除,不走回收站* 如果删除的是有内容的文件夹,则删除失败*/File f4 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile\\a.txt");boolean b4 = f4.delete();System.out.println(b4);}
2.4 File的常见成员方法(获取并遍历)
public static void main(String[] args) {File f = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile");//获取当前该路径下所有内容File[] files = f.listFiles();for (File file : files) {System.out.println(file);}}
public static void main(String[] args) {//0.获取系统中所有的盘符File[] arr = File.listRoots();System.out.println(Arrays.toString(arr));//1.获取当前该路径下所有内容(仅仅能获取名字)File f1 = new File("G:\\code\\Java\\basic_code\\day27_code\\src\\myFile");String[] arr2 = f1.list();System.out.println(Arrays.toString(arr2));//2.利用文件名过滤器获取当前该路径下所有内容//需求:获取文件夹里面所有的.txt文件//方法一:String[] arr3 = f1.list(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {File src = new File(dir, name);return src.isFile() && name.endsWith(".txt");}});System.out.println(Arrays.toString(arr3));//方法二:File[] arr5 = f1.listFiles();for (File file : arr5) {if (file.isFile() && file.getName().endsWith(".txt")) {System.out.println(file);}}//利用文件名过滤器获取当前该路径下所有内容File[] arr6 = f1.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {return pathname.isFile() && pathname.getName().endsWith(".txt");}});System.out.println(Arrays.toString(arr6));File[] arr7 = f1.listFiles(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {File file = new File(dir, name);return file.isFile() && file.getName().endsWith(".txt");}});System.out.println(Arrays.toString(arr7));}
三、综合练习
练习一:(创建文件)
需求:在当前模块下的aaa文件夹中创建一个a.txt文件
public static void main(String[] args) throws IOException {//需求:// 在当前模块下的aaa文件夹中创建一个a.txt文件//0.创建aaa文件夹File f1 = new File("day27_code\\aaa");boolean b = f1.mkdirs();System.out.println(b);//1.创建a.txt文件File f2 = new File(f1,"a.txt");boolean b2 = f2.createNewFile();System.out.println(b2);}
练习二:(单个文件夹查找文件)
需求:定义一个方法找某一个文件夹中,是否有以avi结尾的电影。(暂时不需要考虑字文件夹)
public static void main(String[] args) {//需求:// 定义一个方法找某一个文件夹中,是否有以avi结尾的电影。// (暂时不需要考虑字文件夹)File f = new File("day27_code/aaa");boolean b = haveAvi(f);System.out.println(b);}/*作用:找某一个文件夹中是否有以avi结尾的电影* 形参:要查找的文件* 返回值:查找的结果 存在 true 不存在 false*/private static boolean haveAvi(File file) {File[] files = file.listFiles();for (File f : files) {if (f.isFile() && f.getName().endsWith(".avi")){return true;}}return false;}
练习三:(遍历硬盘查找文件)
需求:找到电脑中所有以avi结尾的电影(需要考虑子文件夹)套路:1. 进入文件夹2. 遍历数组3. 判断4. 判断
public static void main(String[] args) {/*需求:找到电脑中所有以avi结尾的电影(需要考虑子文件夹)*/
// File f = new File("C:/");findAvi();}private static void findAvi(){File[] files = File.listRoots();for (File file : files) {findAvi(file);}}private static void findAvi(File src) {//进入文件夹srcFile[] files = src.listFiles();if (files != null){//遍历数组,依次得到文件夹中的每一个文件或文件夹for (File file : files) {if (file.isFile()) {//判断-是否是文件String name = file.getName();if (name.endsWith(".avi")) {System.out.println(file);}} else {//判断-是否是文件夹//递归findAvi(file);}}}}
练习四:(删除文件夹)
需求:删除一个多级文件夹如果我们要删除一个有内容的文件夹1. 先删除文件夹里面所有的内容2. 再删除自己
public static void main(String[] args) {/*删除一个多级文件夹*/File f = new File("day27_code/aaa");delete(f);}private static void delete(File src) {//1. 先删除文件夹里面所有的内容//进入文件夹File[] files = src.listFiles();//遍历for (File file : files) {//判断是否是文件if (file.isFile()) {file.delete();} else {//判断是否是文件夹delete(file);}}//2. 再删除自己src.delete();}
练习五:(统计文件夹大小)
需求:统计一个文件夹的总大小
public static void main(String[] args) {/* 需求:统计一个文件夹的总大小*/File f = new File("G:\\code\\Java\\basic_code\\day27_code\\src");long len = getLen(f);System.out.println(len);}private static long getLen(File src) {long len = 0;//进入文件夹File[] files = src.listFiles();for (File file : files) {if (file.isFile()) {len += file.length();} else {len += getLen(file);}}return len;}
练习六:(统计各种文件数量)
需求:统计一个文件夹中每种文件的个数并打印(考虑子文件夹)1. 打印格式如下:2. txt:3个3. doc:4个4. jpg:6个
public static void main(String[] args) {/*需求:统计一个文件夹中每种文件的个数并打印(考虑子文件夹)1. 打印格式如下:2. txt:3个3. doc:4个4. jpg:6个*/File f = new File("day27_code/aaa");HashMap<String, Integer> count = getCount(f);System.out.println(count);}/** 作用:* 统计文件夹中文件的个数* 参数* 要统计的那个文件夹* 返回值* Map(后缀名:次数)*/private static HashMap<String, Integer> getCount(File src) {//0.创建集合HashMap<String, Integer> hm = new HashMap<>();//1.进入文件夹File[] files = src.listFiles();//2.遍历for (File file : files) {if (file.isFile()) {//3.判断是文件String name = file.getName();String[] arr = name.split("\\.");if (arr.length >= 2) {String endName = arr[arr.length - 1];if (hm.containsKey(endName)) {int count = hm.get(endName);count++;hm.put(endName, count);} else {hm.put(endName, 1);}}}else {//4.判断是文件夹HashMap<String, Integer> sonMap = getCount(file);//遍历sonMap把里面的值累加到hm当中Set<Map.Entry<String, Integer>> entries = sonMap.entrySet();for (Map.Entry<String, Integer> entry : entries) {String key = entry.getKey();Integer value = entry.getValue();if (hm.containsKey(key)){int count = hm.get(key);count = count + value;hm.put(key,count);}else {hm.put(key,value);}}}}return hm;}