java - day012 - 异常 , throws, throw , IO ,RandomAccessFile
- 异常 封装错误信息的对象
- 错误信息
- 类型 例如: NullPointerExce 空指针
- 提示消息
- 出错的行号
- 异常的继承结构
- Throwable
- | - Error 系统级错误
- | - Exception 可修复的错误
- | - 其他Exception
- | - RuntimeException
- | - NullPointException 空指针
- | - ArrayIndecOutOfBoundException 1 数组下标1越界
- | - ArithmeticException 数学异常
- | - NumberFprmatException 数字格式异常
- | - ClassCastException
- 异常的处理流程
- 程序错误 , 封装成异常对象 , 抛出异常
- 如果没有捕获异常的处理
- 会被JVM 虚拟机接收打印异常信息,并关闭虚拟机
- 异常的捕获
-
try{ }catch(AException e){// 捕获 A 类型异常 }catch(BException e){// 捕获 B 类型异常
}catch(父类型异常 Exception e){如果有父类型放在最后
// 放在第一位,只会执行此异常类型,不会执行其异常类型
}finally{
// 不管出错不出错,都会被执行
// 一般用来清理一些资源
} - throws
- 设置异常的抛出管道
- 方法中要抛出异常, 必须存在对应类的抛出管道
- 在任何方法上都有默认的异常管道: RuntimeException
- RuntimeException 及其子类异常,都可以从默认管道抛出
- 不是RuntimeException类型的异常必须写对应的异常抛出管道
-
private static void f() throws ParseException, IOException {
}
- RuntimeException 及其子类型都有默认的抛出管道
- 非检查异常,编译器编译代码时, 不会检查RuntimeException异常
- 检查异常 (非 RuntimeException )
- 编辑器编辑代码是, 会检查是否捕获异常或添加了管道
- 都没有,会编译失败
- throw
- 手动抛出异常
- 执行异常的抛出动作
-
if (b == 0) { // 新建异常对象, 括号里面可以添加错误信息字符串 ArithmeticException e = new ArithmeticException("不能除0"); // 抛出异常到调用位置 throw e; }
- 异常包装
- 捕获的异常,包装成其他有抛出管道类型,再抛出
- 使用场景
- 不能抛出的异常,包装成能抛出的异常类型再抛
- 异常简化,减少异常管道数量
- 重写方法的异常管道, 不能比父类方法异常管道多,且不能不同于父类的异常管道
-
Collections.sort(list, new Comparator<String>() { @Override public int compare(String o1, String o2) { try { SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd"); Date d1 = sdf.parse(o1); Date d2 = sdf.parse(o2); return d1.compareTo(d2); } catch (ParseException e) { // TODO Auto-generated catch block throw new RuntimeException(e); } } });
- 自定义异常
- 继承RuntimeException 不用写异常管道
- 继承Exception 需要写异常管道
- 使用
- 起一个合适的类名, 见名知意
- 选择一个合适的父类,一般用Exception,RuntimeException
- 添加合适的构造方法
-
/* * 继承 Exception 需要写异常管道抛出 */ public class UserNameNotFoundException extends Exception { public UserNameNotFoundException() { super(); // TODO Auto-generated constructor stub } public UserNameNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public UserNameNotFoundException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public UserNameNotFoundException(String message) { super(message); // TODO Auto-generated constructor stub } public UserNameNotFoundException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
// 使用public class Test1 { public static void main(String[] args) { System.out.println("输入用户名和密码"); String n = new Scanner(System.in).nextLine(); System.out.println("密码"); String p = new Scanner(System.in).nextLine(); try { login(n,p); System.out.println("欢迎登陆"); } catch (UserNameNotFoundException e) { System.out.println("用户名不存在"); }catch (WrongPasswordException e) { System.out.println("密码错误"); } } private static void login(String n, String p) throws UserNameNotFoundException, WrongPasswordException { if (!n.equals("abc")) { throw new UserNameNotFoundException(); } if (!p.equals("123")) { throw new WrongPasswordException(); } } }
- IO input output (输入输出)
- Java.io 包
- File
- RandomAccessFile
- InputStream/OutputStream
- FileInputStream/FileOutStream
- BufferedInputStream/BufferedOutputStream
- ObjectInputStream/ObjectOutputStream
- Reader/Writer
- IputStreamReader/OutputStreamWrite
- File 封装磁盘路径字符串
- 文件路径
- 文件夹路径
- 不存在的路径
- 作用
- 可以获得文件或者文件夹的属性
- length(); 文件字节量,对文件夹无效
- lastModified(); 最后修改时间, 毫秒值
- getName(); 文件名
- getParent(); 父目录
- getAbsolutePath();磁盘完整路径
- isExists(); 是否存在
- isFile();是否是文件
- isDirectory();是否是文件夹
-
//path = "/Users/dingzhijie/Desktop/ceshi.txt"; // 存在的文件 //path = "/Users/dingzhijie/Desktop/ceshi222"; // 存在的文件夹 path = "d:dgv"; // 不存在的路径 File file = new File(path); System.out.println(path); System.out.println(file.exists()); System.out.println(file.length()); System.out.println(file.isFile()); System.out.println(file.isDirectory());
- 可以创建删除文件和文件夹
- creatNewFile();创建文件,
- 必须保证创建文件的文件夹是存在的
- mkdirs();创建多层文件夹
- delete();删除文件,或者空文件夹
-
// 创建文件夹 File dir = new File("/Users/dingzhijie/Desktop/ccc"); if (!dir.isDirectory()) { dir.mkdirs(); } // 创建文件 File file = new File("/Users/dingzhijie/Desktop/cc.txt"); if (!file.isFile()) { file.createNewFile(); } // 删除文件夹 if (dir.exists()) { dir.delete(); } // 删除文件 if (file.exists()) { file.delete(); }
- File.creatTempFile();创建临时文件(静态方法)
- 系统资源紧张的时候,或者管家也会清理临时文件
- \Users\wanght\AppData\Local\Temp
-
/* * 参数: 前缀, 至少三个字符 * 参数: 后缀, 可以不写 null 会自动添加 */ File file = File.createTempFile("abc", ".txt"); System.out.println(file);
-
-
- 对文件夹进行列出所有文件
- list();
- 文件.文件夹名称字符串数组
- listFiles();
- 文件.文件夹封装的 File 数组
-
/* * 如果目录不存在,不能列表 * 或者目录无权访问,也不能列表 */ String[] fileNameArr = dir.list(); File[] listFiles = dir.listFiles(); System.out.println(Arrays.toString(fileNameArr)); for (File file : listFiles) { System.out.println(file.getName()); }
- 求目录中文件的总大小
-
public class Test5 { public static void main(String[] args) { File dir = new File("/Users/dingzhijie/Desktop/未命名文件夹"); if (dir.isDirectory()) { long size = dirLength(dir); System.out.println(size); } } private static long dirLength(File dir) { /* * [a] * | - b * | - c * | - [d] * * 对dir 目录列表 * 吧 列表文件和文件夹大小加一起 */ File[] listFiles = dir.listFiles(); if (listFiles == null) { return 0; } // 累加变量 long sum = 0; for (File file : listFiles) { if (file.isDirectory()) { sum += dirLength(file); // 文件夹递归求子文件夹大小 }else { sum += file.length(); // 文件直接累加 } } return sum; } }
- RandomAccessFile
- control+h 切换文本和数字
- 有一个下标, 读写下标位置的字节值
- 每读写一个字节值, 下标会自动向后移动
- 下标可以任意定位
- 创建对象
- new RandomAccessFile(文件,"r"); // 只读
- new RandomAccessFile(文件,"rw"); // 读写
- 方法
- write(int b);
- int 的 四个字节, 只输出末尾的一个
- 所以只输入 255 范围内的值
- write(byte[]);
- 输出数组中,全部字节值
- write(byte[], start, length);
- 输出数组中, 从 start 位置开始的 length 个字节值
-
package day1204; import java.io.IOException; import java.io.RandomAccessFile; public class Test1 { public static void main(String[] args) throws IOException { /* * 如果文件不存在, 自动新建文件 * 如果文件夹不存在, 会报异常 */ RandomAccessFile raf = new RandomAccessFile("/Users/dingzhijie/Desktop/UE_file1", "rw"); raf.write(97); raf.write(98); raf.write(99); raf.write(356); // byte[] a = {101,102,103,104,105,106,107,108,110}; raf.write(a); // raf.write(a, 2, 4); // 释放系统资源 raf.close(); } }
- read();
- 读取一个字节,再补三个 0 字节,变成 int 类型
- 读取结束,无数据再读取返回 -1
- seek(int position);
- 定位下标到指定的位置
-
// 下标定位到 0 位置 raf.seek(0); // 单字节读取 int b; // 保存读取的字节值 while ((b = raf.read()) != -1) { System.out.println(b); }
- read(byte[] buff);
- 根据数组长度读取一批字节值,并返回这一批数据的数量
- 因为数据数量可能不够数组长度
- 读取结束,无数据再读取返回 -1
-
// 批量读取 raf.seek(0);// 定位下标到 0 byte[] buff = new byte[4]; int c; while ((c = raf.read(buff)) != -1) { System.out.println(c+"\t"+Arrays.toString(buff)); }
- getFilePointer();
- 当前下标所在的位置
- 文件的加密 . 解密
- 用一个值, 对每个字节值求异或
-
package day1301; import java.io.File; import java.io.RandomAccessFile; import java.util.Scanner; public class Test1 { public static void main(String[] args) { System.out.println("输入文件:"); Scanner scanner = new Scanner(System.in); String s = scanner.nextLine(); File file = new File(s); if (!file.isFile()) { System.out.println("不是文件"); return; } System.out.println("加密key:"); int key = scanner.nextInt(); try { encrypt(file,key); System.out.println("加密/解密成功"); } catch (Exception e) { System.out.println("失败"); e.printStackTrace(); } } private static void encrypt(File file, int key) throws Exception { /* * 从文件读取一个字节值 * 对 key 异或后,再写回到文件 */ RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 单字节读写 // int b; // while ((b = raf.read()) != -1) { // b ^= key; // 异或加密, 解密 // // 下标往前挪一位 // raf.seek(raf.getFilePointer()-1); // // 字节值写回到文件 // raf.write(b); // } // 批量读写 byte[] buff = new byte[8192]; // 一般用 8192 , 8k int n; while ((n = raf.read(buff)) != -1) { for (int i = 0; i < n; i++) { buff[i] ^= key; } // 下标前移 n 个位置 raf.seek(raf.getFilePointer()-n); // 写回文件, 从 0 位置开始的 前 n 个写回文件 raf.write(buff, 0, n);; } // 批量读写速度更快, 推荐 raf.close(); } }
没有那个时代犹如现在,知识的爆发和技术的进步如此的迅速,必须不断的学习才能紧跟时代的步伐 . (PS:资料来源比较复杂 ,如有侵权 , 删)